o
    `f,+                     @   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   P/home/ubuntu/webapp/venv/lib/python3.10/site-packages/redis/_parsers/commands.py
<listcomp>       z;AbstractCommandsParser._get_pubsub_keys.<locals>.<listcomp>r   PUBSUB   )CHANNELSNUMSUBSHARDCHANNELSSHARDNUMSUB)	SUBSCRIBE
PSUBSCRIBEUNSUBSCRIBEPUNSUBSCRIBE)PUBLISHSPUBLISH)lenupperlist)selfargscommandkeys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   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   tips   key_specifications	   subcommands)r   intr"   )r%   r'   options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%   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 rD   )isupper)r   xr   r   r   	<genexpr>I   s    z,CommandsParser.initialize.<locals>.<genexpr>)r'   anyappendpoplowerrE   )r%   rrE   uppercase_commandscmdr   r   r   rF   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+   r4   r0   r2   Fr:   |Tc                       g | ]} | qS r   r   r   posr&   r   r   r      r   z+CommandsParser.get_keys.<locals>.<listcomp>r"   rO   rE   splitr$   rF   r   r#   get_get_moveable_keysr*   r   r?   absrange)r%   
redis_connr&   r>   cmd_name_splitr'   r(   	is_subcmdsubcmd_namesubcmdr2   keys_posr   r[   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)r]   r$   execute_commandr	   __str__)r%   rb   r&   piecesr(   emessager   r   r   r_      s   
z!CommandsParser._get_moveable_keysN)r@   rA   rB   __doc__rH   rF   rh   r_   r   r   r   r   rC   8   s    ArC   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.
    )rE   nodereturnNc                 C   s
   i | _ d S rD   )rE   )r%   r   r   r   rH      s   
zAsyncCommandsParser.__init__rs   r   c                    s6   |r|| _ | j dI d H }dd | D | _d S )NCOMMANDc                 S   s   i | ]	\}}|  |qS r   )rO   )r   rR   r'   r   r   r   
<dictcomp>   s    z2AsyncCommandsParser.initialize.<locals>.<dictcomp>)rs   rl   itemsrE   )r%   rs   rE   r   r   r   rF      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 )rS   r   Nr   r   rT   rU   r.   rV   r+   r4   r0   r2   Fr:   rW   Tc                    rX   r   r   rY   r[   r   r   r   	  r   z0AsyncCommandsParser.get_keys.<locals>.<listcomp>r\   )r%   r&   r>   rc   r'   r(   rd   re   rf   r2   rg   r   r[   r   rh      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 )Nri   rj   rk   )rs   rl   r	   rm   )r%   r&   r(   ro   rp   r   r   r   r_     s   
z&AsyncCommandsParser._get_moveable_keys)rt   NrD   )r@   rA   rB   rq   	__slots__rH   r   rF   r   r   strrh   r_   r   r   r   r   rr      s    

"Arr   N)typingr   r   r   r   r   r   redis.exceptionsr   r	   redis.utilsr   redis.asyncio.clusterr   r   rC   rr   r   r   r   r   <module>   s     .u