
    Q
i(                        d Z ddlZddlmZmZmZmZmZmZ ddl	m
Z ddlmZmZmZ ddlmZ ddlmZmZmZ ddlmZ dd	lmZ dd
lmZ  ee          Z G d d          Zdeeef         dedefdZ dedeeef         deeef         fdZ!dS )z
RedisVL Schema Validation Module

This module provides utilities for validating data against RedisVL schemas
using dynamically generated Pydantic models.
    N)AnyDictListOptionalTypeUnion)parse)	BaseModelFieldfield_validator)IndexSchema)	BaseField
FieldTypesVectorDataType)StorageType)TypeInferrer)
get_loggerc                       e Zd ZU dZi Zeeee         f         e	d<   e
dedee         fd            Ze
dededee         fd            Ze
dedee         fd	            Zd
S )SchemaModelGeneratorz
    Generates and caches Pydantic models based on Redis schema definitions.

    This class handles the conversion of RedisVL IndexSchema objects into
    Pydantic models with appropriate field types and validators.
    _model_cacheschemareturnc                    t          t          t          j        |                                d                                                              }|| j        vr|                     |          | j        |<   | j        |         S )z
        Get or create a Pydantic model for a schema.

        Args:
            schema: The IndexSchema to convert to a Pydantic model

        Returns:
            A Pydantic model class that can validate data against the schema
        T)	sort_keys)strhashjsondumpsto_dictencoder   _create_model)clsr   	cache_keys      C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\redisvl/schema/validation.pyget_model_for_schemaz)SchemaModelGenerator.get_model_for_schema!   su     TZ(8(8DIIIPPRRSSTT	C,,,*-*;*;F*C*CCY'	**    fieldstorage_typec                    |j         t          j        k    rt          S |j         t          j        k    rt          S |j         t          j        k    rt          t          t          f         S |j         t          j	        k    rt          S |j         t          j
        k    r_|t          j        k    rH|j        j        t          j        t          j        fv rt$          t                   S t$          t                   S t&          S t)          d|j                    )a?  
        Map Redis field types to appropriate Pydantic types.

        Args:
            field: The Redis field definition
            storage_type: The storage type (HASH or JSON)

        Returns:
            The Pydantic field type

        Raises:
            ValueError: If the field type is not supported
        zUnsupported field type: )typer   TEXTr   TAGNUMERICr   intfloatGEOVECTORr   JSONattrsdatatyper   INT8UINT8r   bytes
ValueError)r"   r'   r(   s      r$   _map_field_to_pydantic_typez0SchemaModelGenerator._map_field_to_pydantic_type4   s    " :((JZ:>))JZ:---e$$Z:>))JZ:,,,{///;'"'"(,    9$E{" @EJ@@AAAr&   c                    |j         j        }i }i }|j                                        D ]\  }}|                     ||          }t
          |         ||<   t          d          ||<   |j        t          j	        k    rdt          fd} ||          |d| <   p|j        t          j        k    rdt          fd}	 |	|          |d| <   |j        t          j        k    rD|j        j        }
|j        j        }dt          dt           dt"          fd	} |||
|          |d| <    |j        di |d
ddd |j         j         d}t          |t(          f|          S )z
        Create a Pydantic model from schema definition using type() approach.

        Args:
            schema: The IndexSchema to convert

        Returns:
            A Pydantic model class with appropriate fields and validators
        N)defaultfnamec                 @     t           d           fd            }|S )Naftermodec                 `    |*t          j        |          st          d d| d          |S )NzGeo field 'z	' value 'z!' is not a valid 'lat,lon' format)r   _is_geographicr8   r"   valuer<   s     r$   _validate_geozUSchemaModelGenerator._create_model.<locals>.make_geo_validator.<locals>._validate_geo}   sM     !,#/#>u#E#E "&0$j%$j$j%$j$j$j'" '" !"  %r&   r   )r<   rE   s   ` r$   make_geo_validatorz>SchemaModelGenerator._create_model.<locals>.make_geo_validator|   s<    $U999% % % % :9% )(r&   	validate_c                 @     t           d           fd            }|S )Nbeforer?   c                 X    t          |t                    rt          d d          |S )NzField 'z' cannot be boolean.)
isinstanceboolr8   rC   s     r$   _disallow_boolzZSchemaModelGenerator._create_model.<locals>.make_numeric_validator.<locals>._disallow_bool   s5    %eT22 T",-Ru-R-R-R"S"SS$r&   rF   )r<   rN   s   ` r$   make_numeric_validatorzBSchemaModelGenerator._create_model.<locals>.make_numeric_validator   s<    $U:::% % % % ;:%
 *)r&   dimsr4   c                 H     t           d           fd            }|S )Nr>   r?   c           
         |t          |t                    rt          |          k    r%t          d d dt          |                     t	                                                    }|dv re|dk    r-t          d |D                       rt          d d          n2|dk    r,t          d	 |D                       rt          d d
          |S )NzVector field 'z' must have z dimensions, got )r5   r6   r5   c              3   .   K   | ]}|d k     p|dk    V  dS )i   N .0vs     r$   	<genexpr>znSchemaModelGenerator._create_model.<locals>.make_vector_validator.<locals>._validate_vector.<locals>.<genexpr>   s/      .R.Rqq4x/B1s7.R.R.R.R.R.Rr&   z6' contains values outside the INT8 range (-128 to 127)r6   c              3   .   K   | ]}|d k     p|dk    V  dS )r      NrU   rV   s     r$   rY   znSchemaModelGenerator._create_model.<locals>.make_vector_validator.<locals>._validate_vector.<locals>.<genexpr>   s/      .O.OAq1u/?C.O.O.O.O.O.Or&   z4' contains values outside the UINT8 range (0 to 255))rL   listlenr8   r   upperany)r"   rD   datatype_strr4   rP   r<   s      r$   _validate_vectorz[SchemaModelGenerator._create_model.<locals>.make_vector_validator.<locals>._validate_vector   s,    !,)%66 .#&u::#5#5*4(o(o(oD(o(ocfglcmcm(o(o+& +& %& 038}}/B/B/D/D#/3D#D#D'3v'='=+..R.RE.R.R.R+R+R ).2<0~0~0~0~3. 3. -.).
 *6)@)@+..O.O.O.O.O+O+O ).2<0|0|0|0|3. 3. -.  %r&   rF   )r<   rP   r4   ra   s   ``` r$   make_vector_validatorzASchemaModelGenerator._create_model.<locals>.make_vector_validator   sJ     %U999% % % % % % :9%8 ,+r&   Tallow)arbitrary_types_allowedextra)__annotations__model_config__PydanticModelrU   )indexr(   fieldsitemsr9   r   r   r*   r   r0   r   r-   r1   r3   rP   r4   r.   r   updatenamer
   )r"   r   r(   annotations
class_dict
field_namer'   
field_typerG   rO   rP   r4   rb   
model_names                 r$   r!   z"SchemaModelGenerator._create_model]   s    |0 ')%'
 "(!4!4!6!6 V	 V	J88MMJ '/z&:K
# &+4%8%8%8Jz" zZ^++)c ) ) ) ) 8J7I*7U7U
3z3344 z111*# * * * * 8N7M8 8
3z3344
 z000{' ;/ , ,&) ,5C ,  ,  ,  ,D 8M7Lh8 8
3z334
 	
 	
 	
#.<@7 S S 	
 	
 	
 ):::
Jj999r&   N)__name__
__module____qualname____doc__r   r   r   r   r
   rf   classmethodr   r%   r   r   r   r9   r!   rU   r&   r$   r   r      s           02L$sDO+,111++ +$y/ + + + [+$ &B&B-8&B	c&B &B &B [&BP t:; t:4	? t: t: t: [t: t: t:r&   r   objpathr   c                     |                     d          sd| }t          |          }|                    |           }|r|d         j        S dS )a  
    Extract a value from a nested JSON object using a JSONPath expression.

    Args:
        obj: The object to extract values from
        path: JSONPath expression (e.g., $.field.subfield, $.[*].name)

    Returns:
        The extracted value or None if not found

    Notes:
        This function uses the jsonpath-ng library for proper JSONPath parsing
        and supports the full JSONPath specification including filters, wildcards,
        and array indexing.
    $z$.r   N)
startswithjsonpath_parsefindrD   )rx   ry   jsonpath_exprmatchess       r$   extract_from_json_pathr      sa    " ??3 D{{ #4((M  %%G   qz4r&   r   c                 n   t                               |           }| j        j        t          j        k    rUi }| j                                        D ]8\  }}|j        rt          ||j                  }||||<   )||v r||         ||<   9n|}|
                    |          }|                    d          S )a)  
    Validate an object against a schema.

    Args:
        schema: The IndexSchema to validate against
        obj: The object to validate

    Returns:
        Validated object with any type coercions applied

    Raises:
        ValueError: If validation fails with enhanced error message
    NT)exclude_none)r   r%   ri   r(   r   r2   rj   rk   ry   r   model_validate
model_dump)r   rx   model_classflat_objrp   r'   rD   	validateds           r$   validate_objectr      s     ';;FCCK | K$444!'!4!4!6!6 	7 	7Jz 7.sEJ??$+0HZ(s""'*:$	7  **844IT222r&   )"rv   r   typingr   r   r   r   r   r   jsonpath_ngr	   r}   pydanticr
   r   r   redisvl.schemar   redisvl.schema.fieldsr   r   r   redisvl.schema.schemar   redisvl.schema.type_utilsr   redisvl.utils.logr   rs   loggerr   r   r   r   rU   r&   r$   <module>r      s     9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 / / / / / / 6 6 6 6 6 6 6 6 6 6 & & & & & & G G G G G G G G G G - - - - - - 2 2 2 2 2 2 ( ( ( ( ( (	H		{: {: {: {: {: {: {: {:|S#X c c    <"3K "3d38n "3c3h "3 "3 "3 "3 "3 "3r&   