o
    Lj2                     @   s   d dl Z d dlZd dlmZmZmZmZ d dlmZ d dl	Z	ddl
mZmZmZmZ ddlmZmZ ddlmZmZ G d	d
 d
eZG dd dee	jjZG dd dee	jjZG dd deZG dd deZdS )    N)JSONDecodeErrorJSONDecoderJSONEncoderloads)Literal   )apply_module_callbacksget_legacy_responsesget_protocol_version	nativestr   )FPHATypeJSONCommands)bulk_of_jsonsdecode_listc                   @   sv   e Zd ZdZde e fddZdd Zdd Zd	d
 Z	dd Z
dd Zedd Zedd Zdd ZdddZdS )	_JSONBasez
    Create a client for talking to json.

    :param decoder:
    :type json.JSONDecoder: An instance of json.JSONDecoder

    :param encoder:
    :type json.JSONEncoder: An instance of json.JSONEncoder
    Nc              
      st   j  j  j dd t j dd  j dd  j d	}i d j d j d j d	 j d
 j dtdtdtd j d fddd fddd j d j d j d j d j }i }ttt j j jdd d}ddd i}	 j j j  jdd d}
| _|j _| _	t
t jt j|||||	|
d _ j D ]\}} j|| q| _| _dS ) z
        Create a client for talking to json.

        :param decoder:
        :type json.JSONDecoder: An instance of json.JSONDecoder

        :param encoder:
        :type json.JSONEncoder: An instance of json.JSONEncoder
        c                 S      | ot | dkS NOKr   r r   Z/home/djax/ivt_ai_plugin/venv/lib/python3.10/site-packages/redis/commands/json/__init__.py<lambda>.       z$_JSONBase.__init__.<locals>.<lambda>c                 S   r   r   r   r   r   r   r   r   0   r   c                 S   r   r   r   r   r   r   r   r   2   r   )	zJSON.ARRPOPz
JSON.DEBUGJSON.GETz
JSON.MERGEz	JSON.MGETz	JSON.MSET	JSON.RESPzJSON.SETJSON.TOGGLEzJSON.ARRAPPENDzJSON.ARRINDEXzJSON.ARRINSERTzJSON.ARRLENzJSON.ARRTRIM
JSON.CLEARJSON.DELJSON.FORGETr   JSON.NUMINCRBYc                    
     | S N_decoder   kwargsselfr   r   r   @      
 JSON.NUMMULTBYc                    r#   r$   r%   r'   r)   r   r   r   A   r+   JSON.OBJKEYSzJSON.STRAPPENDzJSON.OBJLENzJSON.STRLENr   c                 S   s   | d ur| gS | S r$   r   r   r   r   r   r   U       )r   r    r!   r"   r,   r   	JSON.TYPEr/   c                 S   s   | d gkrd S | S r$   r   r   r   r   r   r   X   r.   c                 S   s"   t | trt| dkr| d S | S )Nr   r   )
isinstancelistlenr   r   r   r   r   e   s   " )r"   r,   r-   r   r/   )commonresp2resp3resp2_unifiedresp3_unifiedresp3_to_resp2_legacyN)r&   r   int_decode_json_numop_decode_resp_command_unified_decode_resp3_legacy_numop_resp_floats_to_str_commandclientexecute_commandMODULE_VERSIONr   r
   r	   _MODULE_CALLBACKSitemsset_response_callback__encoder____decoder__)r*   r>   versiondecoderencoderrA   _RESP2_MODULE_CALLBACKS_RESP3_MODULE_CALLBACKS_RESP2_UNIFIED_MODULE_CALLBACKS_RESP3_UNIFIED_MODULE_CALLBACKS'_RESP3_TO_RESP2_LEGACY_MODULE_CALLBACKSkeyvaluer   r)   r   __init__   s   	



z_JSONBase.__init__c                 C   s   |du r|S z| j |}|du rt|W S  ty7   z| j | W  Y S  ty6   t| Y  Y S w  ttfyE   t| Y S w )zGet the decoder.N)rE   decode	TypeErrorAttributeErrorr   r   )r*   objxr   r   r   r&   }   s    z_JSONBase._decodec              	   K   s^   |du r|S z| j t|tr|n| }W n ttfy$   | Y S w t|ts-|g}|S )u9  Decode a JSON.NUMINCRBY / JSON.NUMMULTBY result and normalise
        it to the unified array form.

        RESP2 wire returns a JSON bulk string — a scalar for legacy
        paths and a JSON-encoded list for dollar paths. RESP3 wire
        returns a native list. The unified shape is always a list.
        N)rE   rQ   r0   strrS   r   r1   )r*   rT   r(   resultr   r   r   r:      s   
z_JSONBase._decode_json_numopc                 K   sJ   |  |}|d}t|tr#|ds#t|tr#t|dkr#|d S |S )aj  Decode RESP3 JSON numeric operations back to legacy RESP2 shape.

        RedisJSON returns a RESP3 array for both legacy paths (``.foo``)
        and JSONPath paths (``$.foo``). The command builder records the
        path so default RESP3-wire legacy clients can keep v8 scalar
        results for legacy paths while leaving JSONPath results as lists.
        
_json_path$r   r   )r&   getr0   rV   
startswithr1   r2   )r*   rT   r(   rW   pathr   r   r   r<      s   

z$_JSONBase._decode_resp3_legacy_numopc                 C      |  | |S )zDecode JSON.RESP and lift string-encoded floats inside the
        nested response to native ``float`` values so the unified shape
        matches the RESP3 wire.
        )_convert_resp_floatsr&   r*   rT   r   r   r   r;         z&_JSONBase._decode_resp_command_unifiedc                 C   r]   )zDecode JSON.RESP and re-encode native ``float`` values back
        to their string form so the legacy RESP2 shape is preserved
        when the wire is RESP3.
        )_resp_floats_to_strr&   r_   r   r   r   r=      r`   z%_JSONBase._resp_floats_to_str_commandc              	   C   sf   t | trdd | D S t | ttfr1t | tr|  n| }zt|W S  ttfy0   |  Y S w | S )a2  Recursively convert string-encoded JSON floats.

        RESP2 has no native double type, so JSON.RESP returns JSON floats as
        bulk strings. Any string/bytes leaf that parses as ``float`` is the
        unified representation of such a value; non-numeric strings are left
        untouched.
        c                 S      g | ]}t |qS r   )r   r^   .0itemr   r   r   
<listcomp>       z2_JSONBase._convert_resp_floats.<locals>.<listcomp>)r0   r1   rV   bytesrQ   float
ValueErrorOverflowError)rT   rO   r   r   r   r^      s   
	
z_JSONBase._convert_resp_floatsc                 C   s.   t | trdd | D S t | trt| S | S )zRecursively walk ``obj`` and convert native ``float`` values
        back to their string-encoded form. Lists are walked
        element-wise; non-float leaves are returned unchanged.
        c                 S   rb   r   )r   ra   rc   r   r   r   rf      rg   z1_JSONBase._resp_floats_to_str.<locals>.<listcomp>)r0   r1   ri   rV   )rT   r   r   r   ra      s
   

z_JSONBase._resp_floats_to_strc                 C   s   | j |S )zGet the encoder.)rD   encoder_   r   r   r   _encode   s   z_JSONBase._encodeTc                 C   s   t | jtjr*t| jj| jj| jjj| jj| jj	| jj
 | jj| jj| jjd	}nt| jjt| jj||d}| j|_| j|_|S )aP  Creates a pipeline for the JSON module, that can be used for executing
        JSON commands, as well as classic core commands.

        Usage example:

        r = redis.Redis()
        pipe = r.json().pipeline()
        pipe.jsonset('foo', '.', {'hello!': 'world'})
        pipe.jsonget('foo')
        pipe.jsonget('notakey')
        )	nodes_managercommands_parserstartup_nodesresult_callbackscluster_response_callbackscluster_error_retry_attemptsread_from_replicasreinitialize_stepslock)connection_poolresponse_callbackstransaction
shard_hint)r0   r>   redisRedisClusterClusterPipelinern   ro   rp   rq   rr   retryget_retriesrt   ru   _lockPipelinerw   dictrx   rm   r&   )r*   ry   rz   pr   r   r   pipeline   s*   

z_JSONBase.pipeline)TN)__name__
__module____qualname____doc__r   r   rP   r&   r:   r<   r;   r=   staticmethodr^   ra   rm   r   r   r   r   r   r      s    

`

r   c                   @      e Zd ZdZdS )r}   z Cluster pipeline for the module.Nr   r   r   r   r   r   r   r   r}         r}   c                   @   r   )r   zPipeline for the module.Nr   r   r   r   r   r     r   r   c                   @   s   e Zd ZU dZed ed< dS )JSONF_is_async_clientN)r   r   r   r   r   __annotations__r   r   r   r   r     s   
 r   c                   @   s   e Zd ZU dZed ed< 				ddededededB d	edB d
edB deeB dB dedB fddZ					ddedededB d	edB d
edB deeB dB de
eef fddZdS )	AsyncJSONTr   FNnamer\   	file_namenxxxdecode_keysfphareturnc           
   	      sD   dt dtfdd}t||I dH }	| j|||	||||dI dH S )z
        Set the JSON value at key ``name`` under the ``path`` to the content
        of the json file ``file_name``.

        This runs the blocking file read in a thread pool to avoid blocking
        the event loop.
        fpr   c                 S   s8   t | }t| W  d    S 1 sw   Y  d S r$   )openr   read)r   fr   r   r   
_read_file.  s   

$z&AsyncJSON.set_file.<locals>._read_fileNr   r   r   r   )rV   r   asyncio	to_threadset)
r*   r   r\   r   r   r   r   r   r   file_contentr   r   r   set_file  s   zAsyncJSON.set_file	json_pathroot_folderc              
      s   dt dtt  fdd}i }t||I dH }	|	D ]+}
z|
dd }| j|||
||||dI dH  d	||
< W q tyD   d
||
< Y qw |S )a  
        Iterate over ``root_folder`` and set each JSON file to a value
        under ``json_path`` with the file name as the key.

        This method runs blocking filesystem operations (os.walk and file reads)
        in a thread pool to avoid blocking the event loop.
        folderr   c                 S   s<   g }t | D ]\}}}|D ]}|t j|| qq|S )zCWalk directory and return list of file paths (runs in thread pool).)oswalkappendr\   join)r   
file_pathsrootdirsfilesfiler   r   r   _walk_directoryN  s   z+AsyncJSON.set_path.<locals>._walk_directoryN.r   r   TF)rV   r1   r   r   rsplitr   r   )r*   r   r   r   r   r   r   r   set_files_resultr   	file_pathr   r   r   r   set_path=  s*   	zAsyncJSON.set_path)FFFN)r   r   r   r   r   r   rV   boolr   r   r   r   r   r   r   r   r     sT   
 
	
%

r   )r   r   jsonr   r   r   r   typingr   r{   helpersr   r	   r
   r   commandsr   r   decodersr   r   r   clusterr}   r>   r   r   r   r   r   r   r   <module>   s     |