o
    ;h,+                     @   s~   d dl mZmZmZmZmZmZ d dlmZm	Z	 d dl
mZ er&d dlmZ G dd dZG dd deZG d	d
 d
eZdS )    )TYPE_CHECKINGAnyDictOptionalTupleUnion)
RedisErrorResponseErrorstr_if_bytes)ClusterNodec                   @   s   e Zd Zdd Zdd ZdS )AbstractCommandsParserc                 G   s   t |dk rdS dd |D }|d  }d}|dkr-|d  }|dv r+|dd }|S |d	v r;t|dd }|S |d
v rD|d g}|S )z
        Get the keys from pubsub command.
        Although PubSub commands have predetermined key locations, they are not
        supported in the 'COMMAND's output, so the key positions are hardcoded
        in this method
           Nc                 S      g | ]}t |qS  r
   ).0argr   r   J/var/www/html/venv/lib/python3.10/site-packages/redis/_parsers/commands.py
<listcomp>       z;AbstractCommandsParser._get_pubsub_keys.<locals>.<listcomp>r   ZPUBSUB   )ZCHANNELSZNUMSUBZSHARDCHANNELSZSHARDNUMSUB)Z	SUBSCRIBEZ
PSUBSCRIBEZUNSUBSCRIBEZPUNSUBSCRIBE)ZPUBLISHZSPUBLISH)lenupperlist)selfargscommandkeysZpubsub_typer   r   r   _get_pubsub_keys   s    	
z'AbstractCommandsParser._get_pubsub_keysc                 K   s   i }t |d }||d< t|d |d< dd |d D |d< |d	 |d
< |d |d< |d |d< t|dkrI|d |d< |d |d< |d |d< |S )Nr   namer   Zarityc                 S   r   r   r
   )r   flagr   r   r   r   -   r   z;AbstractCommandsParser.parse_subcommand.<locals>.<listcomp>r   flags   first_key_pos   last_key_pos   
step_count   Ztips   Zkey_specifications	   subcommands)r   intr   )r   r   optionsZcmd_dictcmd_namer   r   r   parse_subcommand(   s   z'AbstractCommandsParser.parse_subcommandN)__name__
__module____qualname__r   r/   r   r   r   r   r   
   s    r   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )CommandsParsera  
    Parses Redis commands to get command keys.
    COMMAND output is used to determine key locations.
    Commands that do not have a predefined key location are flagged with
    'movablekeys', and these commands' keys are determined by the command
    'COMMAND GETKEYS'.
    c                 C   s   i | _ | | d S N)commands
initialize)r   Zredis_connectionr   r   r   __init__A   s   zCommandsParser.__init__c                 C   sX   |  }g }|D ]}tdd |D r|| q|D ]}|||| < q|| _d S )Nc                 s   s    | ]}|  V  qd S r4   )isupper)r   xr   r   r   	<genexpr>I   s    z,CommandsParser.initialize.<locals>.<genexpr>)r   anyappendpoplowerr5   )r   rr5   Zuppercase_commandscmdr   r   r   r6   E   s   

zCommandsParser.initializec                    s  t  dk rdS  d  }|| jvr>| }|d }|| jv r+|t dd   n| | || jvr>t|  d| j|}d|d v rU| j	|g R  }|S d|d v sa|d	 dkrh| j
  }|S |d
 dkr|d dkr|d dkrd}d|v r| d d   }|d D ]}	t|	d |kr| |	}d}q|sdS |d }
|
dk rt  t|
 }
tt|d |
d |d
 } fdd|D }|S )p  
        Get the keys from the passed command.

        NOTE: Due to a bug in redis<7.0, this function does not work properly
        for EVAL or EVALSHA when the `numkeys` arg is 0.
         - issue: https://github.com/redis/redis/issues/9493
         - fix: https://github.com/redis/redis/pull/9733

        So, don't use this function with EVAL or EVALSHA.
        r   Nr   r   ( command doesn't exist in Redis commandsmovablekeysr!   pubsubr   r'   r#   r%   Fr+   |Tc                       g | ]} | qS r   r   r   posr   r   r   r      r   z+CommandsParser.get_keys.<locals>.<listcomp>r   r>   r5   splitr   r6   r   r   get_get_moveable_keysr   r   r/   absrange)r   
redis_connr   r.   cmd_name_splitr   r   	is_subcmdsubcmd_namesubcmdr%   keys_posr   rI   r   get_keysR   sR   





zCommandsParser.get_keysc              
   G   sx   |d   t|dd  }z|jdg|R  }W |S  ty; } z| }d|v s.d|v r5W Y d}~dS |d}~ww )aA  
        NOTE: Due to a bug in redis<7.0, this function does not work properly
        for EVAL or EVALSHA when the `numkeys` arg is 0.
         - issue: https://github.com/redis/redis/issues/9493
         - fix: https://github.com/redis/redis/pull/9733

        So, don't use this function with EVAL or EVALSHA.
        r   r   NCOMMAND GETKEYSInvalid arguments The command has no key arguments)rK   r   execute_commandr	   __str__)r   rP   r   piecesr   emessager   r   r   rM      s   
z!CommandsParser._get_moveable_keysN)r0   r1   r2   __doc__r7   r6   rV   rM   r   r   r   r   r3   8   s    Ar3   c                   @   sr   e Zd ZdZdZdddZdded ddfd	d
Zdedee	e
df  fddZdedee	e
df  fddZdS )AsyncCommandsParsera%  
    Parses Redis commands to get command keys.

    COMMAND output is used to determine key locations.
    Commands that do not have a predefined key location are flagged with 'movablekeys',
    and these commands' keys are determined by the command 'COMMAND GETKEYS'.

    NOTE: Due to a bug in redis<7.0, this does not work properly
    for EVAL or EVALSHA when the `numkeys` arg is 0.
     - issue: https://github.com/redis/redis/issues/9493
     - fix: https://github.com/redis/redis/pull/9733

    So, don't use this with EVAL or EVALSHA.
    )r5   nodereturnNc                 C   s
   i | _ d S r4   )r5   )r   r   r   r   r7      s   
zAsyncCommandsParser.__init__ra   r   c                    s6   |r|| _ | j dI d H }dd | D | _d S )NZCOMMANDc                 S   s   i | ]	\}}|  |qS r   )r>   )r   r@   r   r   r   r   
<dictcomp>   s    z2AsyncCommandsParser.initialize.<locals>.<dictcomp>)ra   rZ   itemsr5   )r   ra   r5   r   r   r   r6      s
   zAsyncCommandsParser.initializer   .c                    s  t  dk r	dS  d  }|| jvrA| }|d }|| jv r,|t dd   n|  I dH  || jvrAt|  d| j|}d|d v rW| j	  I dH }|S d|d v sc|d	 dkrj| j
  }|S |d
 dkr|d dkr|d dkrd}d|v r| d d   }|d D ]}t|d |kr| |}d}q|sdS |d }	|	dk rt  t|	 }	tt|d |	d |d
 }
 fdd|
D }|S )rA   r   Nr   r   rB   rC   r!   rD   r   r'   r#   r%   Fr+   rE   Tc                    rF   r   r   rG   rI   r   r   r   	  r   z0AsyncCommandsParser.get_keys.<locals>.<listcomp>rJ   )r   r   r.   rQ   r   r   rR   rS   rT   r%   rU   r   rI   r   rV      sT   




zAsyncCommandsParser.get_keysc              
      sf   z| j jdg|R  I d H }W |S  ty2 } z| }d|v s%d|v r,W Y d }~d S |d }~ww )NrW   rX   rY   )ra   rZ   r	   r[   )r   r   r   r]   r^   r   r   r   rM     s   
z&AsyncCommandsParser._get_moveable_keys)rb   Nr4   )r0   r1   r2   r_   	__slots__r7   r   r6   r   r   strrV   rM   r   r   r   r   r`      s    

"Ar`   N)typingr   r   r   r   r   r   Zredis.exceptionsr   r	   Zredis.utilsr   Zredis.asyncio.clusterr   r   r3   r`   r   r   r   r   <module>   s     .u