
    2i\H                        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mZmZm	Z	m
Z
mZmZmZmZmZmZ d dlZd dlmZmZmZmZmZ ddlmZ ddlmZ ddlmZmZm Z m!Z!m"Z"m#Z# ddl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, dd	l-m.Z.  ej^                  d
      Z0dedefdZ1dee2   deeee   f   fdZ3de4de4de4fdZ5da6de4fdZ7 G d d      Z8y)    N)ListAnyTupleOptionalCallableUnionMatchAnyStr	GeneratorSequenceType)XStreamZSetHashExpiringMembersSet
ClientInfo   )_msgs)extract_args)IntFloatSUPPORTED_COMMANDSCOMMANDS_WITH_SUB	SignatureCommandItem)SimpleErrorvalid_response_typeSimpleString
NoResponse	casematchcompile_patternQUEUEDdecode_command_bytes)ResponseErrorType	fakeredisvalreturnc                    t        | t              r| j                         S t        | t              rt	        j                  | d      S t        | t
              rBt        t        j                  | j                                }|D cg c]  }t        |       c}S t        | t        t        f      r| D cg c]  }t        |       }}|S | S c c}w c c}w )NF)humanfriendly)
isinstancestrencodefloatr   dictlist	itertoolschainitems_convert_to_resp2tuple)r&   resultitemress       c/mnt/e/genesis-system/.venvs/voice-bridge/lib/python3.12/site-packages/fakeredis/_basefakesocket.pyr3   r3      s    #szz|#u||Cu55#tioosyy{344:;D!$';;#e}%3674 &77
J	 <7s   C4Cfieldsc                     t        | d         }|t        v r+t        |       dk\  r|dt        | d         z   z  }| dd }||fS | dd }||fS )a  Extracts the command and command arguments from a list of `bytes` fields.

    :param fields: A list of `bytes` fields containing the command and command arguments.
    :return: A tuple of the command and command arguments.

    Example:
        ```
        fields = [b'GET', b'key1']
        result = _extract_command(fields)
        print(result) # ('GET', ['key1'])
        ```
    r       r   N)r#   r   len)r9   cmdcmd_argumentss      r8   _extract_commandr@   +   so     vay
)C
CK1$4s)&)444qr
  qr
    x
bits_countc                 X    d}t        |      D ]  }| |z	  dz  s|d|dz
  |z
  z  z  } |S )Nr   r   )range)rB   rC   r5   is       r8   bin_reverserG   A   sE    F: 0Fa<aJNQ.//F0 MrA      c                  $    t         } t         dz  a | S )Nr   )_next_file_no)r5   s    r8   _get_next_file_norK   L   s    FQMMrA   c                       e Zd ZU eg df   ed<   h dZej                  Zddde	de
ded	ed
df fdZed
efd       Zed
ee	df   fd       Zed
efd       Zded
dfdZd7dZd7dZded
dfdZd
e	fdZded
dfdZd7dZeded
eeef   fd       Zd
ededf   fdZdee   d
dfdZ de!eegef      de"dee   d e#d
ef
d!Z$d"e%d
e&fd#Z'd$ed
efd%Z(d&e!e)e*e	f      dee#gef   d
efd'Z+d(ed
ee!eegef      e"f   fd)Z,d*e-d
dfd+Z.d,e/e   d-e	ded
ee)eee   f      fd.Z0d/e1d0e*d
e	fd1Z2d2e*d3e#d
efd4Z3d2e	d
efd5Z4ed/e1d
e5fd6       Z6 xZ7S )8BaseFakeSocketN_clear_watches>   ping	subscribe
psubscribe
ssubscribeunsubscribepunsubscribesunsubscribeserver
FakeServerdbclient_classargskwargsr'   c                    t        t        | 
  |i | ddlm} || _        t               | _        || _        |j                  | j                     | _
        || _        t        j                         | _        d| _        | j!                         | _        | j"                  j%                  d        |  |  |  |  |j'                  di       }t)        di || _        | j
                  j,                  j/                  |        y )Nr   )rW   Fclient_info )superrM   __init__r%   rW   _serverrK   _fileno_db_numdbs_db_client_classqueueQueue	responses_paused_parse_commands_parsersendpopr   _client_infosocketsappend)	selfrV   rX   rY   rZ   r[   rW   info	__class__s	           r8   r`   zBaseFakeSocket.__init__`   s     	nd,d=f=(#)(*::dll+)7<{{} ++-$zz-,&..##D)rA   c                 .    | j                   j                  S N)ro   userrr   s    r8   current_userzBaseFakeSocket.current_user   s      %%%rA   .c                 .    | j                   j                  S rv   )ra   versionrx   s    r8   r{   zBaseFakeSocket.version   s    ||###rA   c                 .    | j                   j                  S rv   )ra   server_typerx   s    r8   r}   zBaseFakeSocket.server_type   s    ||'''rA   msgc                 D    | j                   }|r|j                  |       yy)zgPut a response message into the queue of responses.

        :param msg: The response message.
        N)ri   put)rr   r~   ri   s      r8   put_responsezBaseFakeSocket.put_response   s!     NN	MM# rA   c                     d| _         y )NT)rj   rx   s    r8   pausezBaseFakeSocket.pause   s	    rA   c                 H    d| _         | j                  j                  d       y )NFrA   )rj   rl   rm   rx   s    r8   resumezBaseFakeSocket.resume   s    #rA   _c                 8    | j                   j                          y rv   )rl   close)rr   r   s     r8   shutdownzBaseFakeSocket.shutdown   s    rA   c                     | j                   S rv   )rb   rx   s    r8   filenozBaseFakeSocket.fileno   s    ||rA   c                     |j                   j                         D ]  }|j                  |         |j                  j                         D ]  }|j                  |         | j	                          y)zRemove all the references to `self` from `server`.

        This is called with the server lock held, but it may be some time after
        self.close.
        N)subscribersvaluesdiscardpsubscribersrN   )rr   rV   subss      r8   _cleanupzBaseFakeSocket._cleanup   sd     &&--/ 	DLL	''..0 	DLL	rA   c                     | j                   j                  j                  |        | j                   j                  j	                  t        j                  |              d | _         d | _        d | _        y rv   )	ra   rp   removeclosed_socketsrq   weakrefrefre   ri   rx   s    r8   r   zBaseFakeSocket.close   sR    
 	##D)##**7;;t+<=rA   bufc                 6   | j                  d      dz   }|dk  rDt        t        j                  j	                  | j                         j                                     | d | }| |d  } |j                  d      s|j                         j                         j                  d      d   }dj                  |j                         j                         j                  d      dd        }t        t        j                  j	                  |      d| dz         || fS )N   
r   r   s   
r<   'z' )
findr   msgsUNKNOWN_COMMAND_MSGformatdecodestripendswithsplitjoin)r   poslinecommandrZ   s        r8   _extract_linezBaseFakeSocket._extract_line   s    hhuo!!8d66==cjjl>P>P>RSTT4Cy#$i}}W%kkm))+11#6q9G88DKKM//177<QR@ADd66==gF1TFRTUVVSyrA   c              #     K   d}	 | j                   sd|vr|dz  }| j                   rd|vr| j                  |      \  }}|dd dk(  sDt        t        j                  j                  |j                         j                                     t        |dd       }g }t        |      D ]  }d|vr|dz  }d|vr| j                  |      \  }}|dd dk7  rDt        t        j                  j                  |j                         j                                     t        |dd       }t        |      |dz   k  r|dz  }t        |      |dz   k  r|j                  |d|        ||dz   d } | j                  |       w)	zGenerator that parses commands.

        It is fed pieces of redis protocol data (via `send`) and calls
        `_process_command` whenever it has a complete one.
        rA   r   Nr      *   $r;   )rj   r   r   r   r   r   r   r   intrE   r=   rq   _process_command)rr   r   r   n_fieldsr9   rF   lengths          r8   rk   zBaseFakeSocket._parse_commands   s     ,,%s"2u ,,%s"2**3/ID#8t#!$":":"A"A#**,BTBTBV"WXX4":HF8_ 
(3&5LC 3& ..s3	c8t#%d&>&>&E&EcjjlFXFXFZ&[\\T!BZ#h!+5LC #h!+c'6l+&1*,'
( !!&)' s   'FFBF=BF1Fr9   c                 V   |sy t         j                  d| j                  j                  d       d|        t	        |      \  }}	 | j                  |      \  }}| j                  j                  j                  | j                  j                  | j                  j                         |       | j                  j                  5  	 	 | j                  j                  j                         } |       }|r|j                  | j                         	 K# t        $ r Y nw xY wt!        j                          }| j                  j"                  j%                         D ]	  }	||	_         |j'                  || j(                         | j*                  At,        j.                  |j0                  vr%| j*                  j3                  |||f       t4        }
n| j7                  |||d      }
d d d        n# 1 sw Y   nxY wn# t8        $ rt}| j*                  d| _        |dk(  rP|j<                  j?                  d      r5d|j<                  d	d  z   |_        d | _        d| _        | jA                          |}
Y d }~nd }~ww xY w| jC                  
      }
tE        |
tF              s| jI                  |
       y y )
Nz>>> raddrz: TFexeczERR z,EXECABORT Transaction discarded because of:    )%LOGGERdebugro   getr@   _name_to_funcra   aclvalidate_commandrw   as_byteslockr   rn   r   
IndexErrortimerd   r   check_arityr{   _transactionr   FLAG_TRANSACTIONflagsrq   r"   _run_commandr   _transaction_failedvalue
startswithrN   _decode_resultr*   r   r   )rr   r9   r>   r?   funcsig	weak_socksocknowrX   r5   excs               r8   r   zBaseFakeSocket._process_command   sS   tD--11':;2fXFG-f5]"	**3/ID#LL--d.?.?.D.DdFWFWF`F`Fbdjk"" P8$(LL$?$?$C$C$E	  ){ MM$,,7  &  iik,,**113 "B!BG"t||<$$0T5J5JRUR[R[5[%%,,dC-GH#F!..tS-OF'P P P(  
	  , ,0(f}!5!5f!=JSYYWXWY]Z	$(!+0(##%F
	 $$V,&*-f% .sW   A=G7 G*$D+&G*	DG*DCG*!	G7 *G3/G7 7	I4 A*I//I4r   r   from_scriptc                 0   g }	 |j                  || j                  | j                        }|r5t        j                  |j
                  v rt        t        j                        | j                  r5|j                  t        j                  vrt        t        j                        t        |      dk(  r|d   }n|\  }} || }| j                  j                  dk(  r't        j                   |j
                  vrt#        |      }t        j                   |j
                  vr.t%        || j                  j                        st'        d|       |D ].  }	|	j)                  t        j*                  |j
                  v       0 |S # t        $ r}|}Y d }~Ed }~ww xY w)Nr   r   r;   zInvalid response type for )remove_empty_val)applyre   r{   r   FLAG_NO_SCRIPTr   r   COMMAND_IN_SCRIPT_MSG_pubsubnamerM   ACCEPTED_COMMANDS_WHILE_PUBSUBBAD_COMMAND_IN_PUBSUB_MSGr=   ro   protocol_versionFLAG_SKIP_CONVERT_TO_RESP2r3   r   AssertionError	writebackFLAG_LEAVE_EMPTY_VAL)
rr   r   r   rZ   r   command_itemsretr5   r   command_items
             r8   r   zBaseFakeSocket._run_command  sb    ,.	))D$((DLL9Ct22cii?!$"<"<==||0]0] ]!$"@"@AA3x1}Q&)#mt$$55:t?^?^fifofo?o.v6F22#))CL_D-->>M )+EfX)NOO * 	`L""D4M4MUXU^U^4^"_	`	  	F	s   EF   	F	FFerrorc                     | j                   j                  j                  d      r(ddlm}  |d      j                  |j                        S ddlm}  |d      j                  |j                        S )Nvalkeyr   )DefaultParseri   )socket_read_size)rf   
__module__r   valkey.connectionr   parse_errorr   redis.connection)rr   r   ValkeyDefaultParserRedisDefaultParsers       r8   _decode_errorzBaseFakeSocket._decode_error-  sV    ((33H=N&>JJ5;;WWL%u=II%++VVrA   r5   c                     t        |t              r|D cg c]  }| j                  |       c}S t        |t              r|j                  S t        |t
              r| j                  |      S |S c c}w )z1Convert SimpleString and SimpleError, recursively)r*   r/   r   r   r   r   r   )rr   r5   rs      r8   r   zBaseFakeSocket._decode_result7  sa    fd#4:;qD''*;;-<<,%%f--M <s   A/timeoutc                     |d      }|| j                   r|S |rt        j                         |z   nd}	 ||t        j                         z
  nd}||dk  ry| j                  j                  j	                  |      du ry |d      }||S Y)a  Run a function until it succeeds or timeout is reached.

        The timeout is in seconds, and 0 means infinite. The function
        is called with a boolean to indicate whether this is the first call.
        If it returns None, it is considered to have "failed" and is retried
        each time the condition variable is notified, until the timeout is
        reached.

        Returns the function return value, or None if the timeout has passed.
        TNr   )r   F)_in_transactionr   re   	conditionwait)rr   r   r   r   deadlines        r8   	_blockingzBaseFakeSocket._blockingB  s     4j?d22J,3499;(2:2Fx$))+-DG"w!|xx!!&&w&75@u+C
 rA   cmd_namec                    |t         vrJ|j                  dd      j                  dd      }t        t        j                  j                  |            t         |   }| j                  j                  |j                  vrJ|j                  dd      j                  dd      }t        t        j                  j                  |            t        | |j                  d      }||fS )z7Get the signature and the method from the command name.r<   
N)r   replacer   r   r   r   ra   r}   server_typesgetattr	func_name)rr   r   
clean_namer   r   s        r8   r   zBaseFakeSocket._name_to_func[  s    --!))$4<<T3GJd66==jIJJ *<<##3+;+;;!))$4<<T3GJd66==jIJJtS]]D1SyrA   datac                     | j                   j                  s| j                  t        j                        t        |t              r|j                  d      }| j                  j                  |       y )Nascii)
ra   	connected_connection_error_classr   CONNECTION_ERROR_MSGr*   r+   r,   rl   rm   )rr   r   s     r8   sendallzBaseFakeSocket.sendalli  sP    ||%%..t/H/HIIdC ;;w'D$rA   keyscursorc                     t        |      }t        |d      \  \  }}}|dn|}t        |      }t        |      dz
  j	                         }t        ||      }|t        |      k\  rdg gS ||z   }	g }
|t        |      nddt        dt        t        t        t           df   ffd}dt        dt        f fd	}|Zt        j                  ||||z         D ]<  }t        |t              r|d
   n|} ||      s# ||      s,|
j                  |       > n||||z    }
|	t        |      k\  rd
}	t!        t        |	|            j#                         |
gS )a  This is the basis of most of the ``scan`` methods.

        This implementation is KNOWN to be un-performant, as it requires grabbing the full set of keys over which
        we are investigating subsets.

        The SCAN command, and the other commands in the SCAN family, are able to provide to the user a set of
        guarantees associated with full iterations.

        - A full iteration always retrieves all the elements that were present in the collection from the start to the
          end of a full iteration. This means that if a given element is inside the collection when an iteration is
          started and is still there when an iteration terminates, then at some point the SCAN command returned it to
          the user.

        - A full iteration never returns any element that was NOT present in the collection from the start to the end
          of a full iteration. So if an element was removed before the start of an iteration and is never added back
          to the collection for all the time an iteration lasts, the SCAN command ensures that this element will never
          be returned.

        However, because the SCAN command has very little state associated (just the cursor),
        it has the following drawbacks:

        - A given element may be returned multiple times. It is up to the application to handle the case of duplicated
          elements, for example, only using the returned elements to perform operations that are safe when re-applied
          multiple times.
        - Elements that were not constantly present in the collection during a full iteration may be returned or not:
          it is undefined.

        )z*matchz*typez+countN
   r      0keyr'   c                 p    t        | t              r| j                  d      } j                  |       S dS )Nzutf-8T)r*   r+   r,   match)r
  regexs    r8   	match_keyz'BaseFakeSocket._scan.<locals>.match_key  s4    #s#jj)','85;;s#BdBrA   c                 |    d u xs6 t        t        j                  j                  |          j                        S rv   )r    rM   _key_value_typere   r   )r
  _typerr   s    r8   
match_typez(BaseFakeSocket._scan.<locals>.match_type  s4    D=iIn.L.LTXXVY].[.a.ach$iirA   r   )r   r   sortedr=   
bit_lengthrG   r!   bytesr   boolr	   r0   islicer*   r4   rq   r+   r,   )rr   r  r  rZ   patterncountr   r   bits_lenresult_cursorresult_datar  r  r&   compare_valr  r  s   `              @@r8   _scanzBaseFakeSocket._scanp  sq   : V%1$8U%V"%md|IM--/VX.SY":,3,?(T	C5 	CU4ut+C%D 	C
	jE 	jd 	j %"3 ''ffunE ,(23(>c!fC[)j.E&&s+,
 v7KCI%MKx89@@BKPPrA   r
  scalec                     |sy|j                   yt        t        |j                   | j                  j                  z
  |z              S )Nr   )expireatr   roundre   r   )rr   r
  r  s      r8   _ttlzBaseFakeSocket._ttl  s;    \\!ucllTXX]]:eCDEErA   r   r)   c                 V    | j                   dk\  rd|z   }t        j                  ||      S N)   r   )r{   r   r,   )rr   r   r)   s      r8   _encodefloatzBaseFakeSocket._encodefloat  s(    <<4IE||E=11rA   c                 T    | j                   dk\  rd|z   }t        j                  |      S r&  )r{   r   r,   )rr   r   s     r8   
_encodeintzBaseFakeSocket._encodeint  s&    <<4IEzz%  rA   c                    | j                   t        d      S t        | j                   t              rt        d      S t        | j                   t              rt        d      S t        | j                   t
              rt        d      S t        | j                   t              rt        d      S t        | j                   t              rt        d      S t        | j                   t              rt        d      S J )Ns   nones   strings   lists   sets   zsets   hashs   stream)	r   r   r*   r  r/   r   r   r   r   )r
  s    r8   r  zBaseFakeSocket._key_value_type  s    99((		5)	**		4(((		#56''		4(((		4(((		7+	**5rA   )r'   N)8__name__r   __qualname__r   __annotations__r   redisConnectionErrorr  r   r   r   r`   propertyr  ry   r   r{   r+   r}   r   r   r   r   r   r   r   staticmethodr   r   rk   r   r   r   r   r  r   r   r$   r   r   r   r-   r   r   r
   r  r   r  r   r$  r(  r*  r   r  __classcell__)rt   s   @r8   rM   rM   S   s   RX&&&" $33** * 	*
 * * 
*@ &e & & $sCx $ $ (S ( (
 
 
# $  
s 
t 
	 
5 
U5%<%8 
 
*4d?!; *8+&tE{ +&t +&ZXseSj129BJNs)bf	6W; W3D W	S 	S 	%s
*;!< HdVUX[DY ^a 2c eHXseSj=Q4RT]4].^  F  t  <Q(5/ <Q3 <Qu <QeTY[_`e[fTfNgIh <Q|F FE Fc F2% 2 2 2
! ! !
 [ \  rA   rM   )9r0   loggingrg   r   r   typingr   r   r   r   r   r   r	   r
   r   r   r   r/  fakeredis.modelr   r   r   r   r    r   r   _command_args_parsingr   	_commandsr   r   r   r   r   r   _helpersr   r   r   r   r    r!   r"   r#   _typingr$   	getLoggerr   r3   r  r@   r   rG   rJ   rK   rM   r^   rA   r8   <module>r=     s         h h h h  O O  / ` `	 	 	 '			;	'3 3 T%[ U3S	>-B ,3 C C  3 ~ ~rA   