o
    iK                     @  s  U d Z ddlmZ ddlZddlZddlZddl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ZddlmZ ddlZddlmZ d	d
lmZmZ d	dlmZ eroddlmZ ddlmZmZ ddlm Z m!Z! ej"#dZ$e$%dZ&G dd deddZ'G dd deddZ(G dd dZ)dNddZ*eG dd  d Z+e+ Z,d!Z-d"e.d#< e/d$d% e-D Z0d"e.d&< da1d'e.d(< dOd*d+Z2dPd.d/Z3dQd3d4Z4e	d5d6 Z5e	d7d8 Z6ed9Z7ed:Z8dRd?d@Z9dSdDdEZ:dTdHdIZ;dUdLdMZ<dS )Vz.Integration for instrumenting Pydantic models.    )annotationsN)	dataclass)	lru_cache)TYPE_CHECKINGAnyCallableLiteral	TypedDictTypeVar)	ParamSpec)LogfireSpan   )GLOBAL_CONFIGPydanticPlugin)get_versionValidationError)
SchemaKindSchemaTypePath)
CoreConfig
CoreSchemazlogfire.pydanticzpydantic.validationsc                   @  s   e Zd ZU dZded< dS )PluginSettingsa  A typed dict for the Pydantic plugin settings.

    This is how you can use the [`PluginSettings`][logfire.integrations.pydantic.PluginSettings]
    with a Pydantic model:

    ```py
    from logfire.integrations.pydantic import PluginSettings
    from pydantic import BaseModel


    class Model(BaseModel, plugin_settings=PluginSettings(logfire={'record': 'all'})):
        a: int
    ```
    LogfireSettingslogfireN__name__
__module____qualname____doc____annotations__ r    r    c/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/logfire/integrations/pydantic.pyr      s   
 r   F)totalc                   @  s.   e Zd ZU dZded< 	 ded< 	 ded< dS )	r   z%Settings for the logfire integration.floattrace_sample_ratez	list[str]tags$Literal['all', 'failure', 'metrics']recordNr   r    r    r    r!   r   3   s   
 r   c                   @  sx   e Zd ZdZdZd5ddZd6ddZd7ddZd8ddZd9d!d"Z	d:d#d$Z
d;d'd(Zd<d)d*Zd=d0d1Zd>d2d3Zd4S )?_ValidateWrapperz2Decorator factory for one schema validator method.)validation_methodschema_name_record_logfirer)   ?Literal['validate_python', 'validate_json', 'validate_strings']schemar   _configCoreConfig | None_plugin_settingsPluginSettings | dict[str, Any]schema_type_pathr   r'   r&   returnNonec                 C  sZ   || _ t|| _|| _tj| _|di d}|r+t|t	r"|g}| jj
| | _d S d S )Nr   r%   )r)   get_schema_namer*   r+   r   DEFAULT_LOGFIRE_INSTANCEr,   get
isinstancestr	with_tags)selfr)   r.   r/   r1   r3   r'   r%   r    r    r!   __init__O   s   	

z_ValidateWrapper.__init__	validatorr   c                   s   ddl m  jdkrtd fd	d
}|S jdkr0td fdd
}|S jdks7J tdfdd
}|S )zEDecorator which wraps a schema validator method with instrumentation.r   r   all
input_datar   argskwargsr4   c              
     s   t js| g|R i |S | }z| g|R i |}W n1  y9 } z|| jdd  d }~w tyQ } z|| jdd  d }~ww || jdd |S NF)successT)r   _initialized	_on_enter_on_error_span_count_validation	Exception_on_exception_span_on_success)r@   rA   rB   spanresulterror	exceptionr   r<   r>   r    r!   wrapped_validatorq   s&   
z4_ValidateWrapper.__call__.<locals>.wrapped_validatorfailurec              
     s   t js| g|R i |S z| g|R i |}W n/  y3 } zjdd |  d }~w tyJ } zjdd |  d }~ww jdd |S rC   )r   rE   rH   _on_error_logrI   _on_exception_log)r@   rA   rB   rM   rN   rO   rP   r    r!   rQ      s"   

metricsc                   sd   t js| g|R i |S z| g|R i |}W n ty)    jdd  w  jdd |S rC   )r   rE   rI   rH   )r@   rA   rB   rM   )r<   r>   r    r!   rQ      s   N)r@   r   rA   r   rB   r   r4   r   )pydanticr   r+   	functoolswraps)r<   r>   rQ   r    rP   r!   __call__j   s   
D
$z_ValidateWrapper.__call__r@   c                 C  s(   | j jd| j| j|dd| j d S )Nz*Pydantic {schema_name} {validation_method}infoz	pydantic.)r*   r)   r@   _level
_span_name)r,   rL   r*   r)   	__enter__)r<   r@   r    r    r!   rF      s   
z_ValidateWrapper._on_enterrL   r   rM   c                 C  s$   | j |dd|d |d d d  d S )NT	succeeded)rD   statusrM   )_set_span_attributes__exit__)r<   rL   rM   r    r    r!   rK      s   z_ValidateWrapper._on_successrN   r   c                 C  s,   | j jdd| j| |jdddd d S )Nwarnz"Validation on {schema_name} failedFinclude_url)r*   error_counterrors)levelmsg_template
attributes)r,   logr*   re   rf   )r<   rN   r    r    r!   rS      s   

z_ValidateWrapper._on_error_logc                 C  s<   | j |dd| |jddd |d |d d d  d S )NFfailedrc   )rD   r_   re   rf   rb   )r`   re   rf   	set_levelra   )r<   rL   rN   r    r    r!   rG      s   

z_ValidateWrapper._on_error_spanrO   rI   c                 C  s&   | j jdd| jt|jd|d d S )NrN   z3Validation on {schema_name} raised {exception_type})r*   exception_type)rg   rh   ri   exc_info)r,   rj   r*   typer   )r<   rO   r    r    r!   rT      s   
z"_ValidateWrapper._on_exception_logc                 C  s4   | j |ddt|j d |t|||j d S )NFzraised )rD   r_   )r`   ro   r   ra   __traceback__)r<   rL   rO   r    r    r!   rJ      s   z#_ValidateWrapper._on_exception_spanr_   r:   rD   boolri   c                K  s4   |  r|d|i| | jd| 7  _d S d S )NrD    )is_recordingset_attributesmessage)r<   rL   r_   rD   ri   r    r    r!   r`      s   z%_ValidateWrapper._set_span_attributesc                C  s   t d|| j| jd d S )N   )rD   r*   r)   )validation_counteraddr*   r)   )r<   rD   r    r    r!   rH      s   z"_ValidateWrapper._count_validationN)r)   r-   r.   r   r/   r0   r1   r2   r3   r   r'   r&   r4   r5   )r>   r   r4   r   )r@   r   )rL   r   rM   r   )rN   r   )rL   r   rN   r   )rO   rI   )rL   r   rO   rI   )
rL   r   r_   r:   rD   rq   ri   r   r4   r5   )rD   rq   r4   r5   )r   r   r   r   	__slots__r=   rY   rF   rK   rS   rG   rT   rJ   r`   rH   r    r    r    r!   r(   E   s    


N


	



r(   r.   r   r4   r:   c                   s   | d dv r| d j S | d dv rt| d S | d dkr?| d }|d dkr;|d   fd	d
| d D \}t|S t|S | d S )a  Find the best name to use for a schema.

    The follow rules are used:
    * If the schema represents a model or dataclass, use the name of the class.
    * If the root schema is a wrap/before/after validator, look at its `schema` property.
    * Otherwise use the schema's `type` property.

    Args:
        schema: The schema to get the name for.

    Returns:
        The name of the schema.
    ro   >   modelr   cls>   function-wrapfunction-afterfunction-beforer.   definitionszdefinition-ref
schema_refc                   s   g | ]
}|d   kr|qS )refr    ).0
definitionr   r    r!   
<listcomp>  s
    z#get_schema_name.<locals>.<listcomp>)r   r6   )r.   inner_schemaschema_definitionr    r   r!   r6      s   

r6   c                   @  sJ   e Zd ZdZeejedk sej	ddkrdd
dZ
dS dddZ
dS )LogfirePydanticPlugina  Implements a new API for pydantic plugins.

    Patches Pydantic to accept this new API shape.

    Set the `LOGFIRE_PYDANTIC_RECORD` environment variable to `"off"` to disable the plugin, or
    `PYDANTIC_DISABLE_PLUGINS` to `true` to disable all Pydantic plugins.
    z2.5.0LOGFIRE_PYDANTIC_RECORDoff_r   __r4   /tuple[_ValidateWrapper, ...] | tuple[None, ...]c                 O  s   dS )zBackwards compatibility for Pydantic < 2.5.0.

            This method is called every time a new `SchemaValidator` is created, and is a NO-OP for Pydantic < 2.5.0.
            NNNr    )r<   r   r   r    r    r!   new_schema_validator-  s   z*LogfirePydanticPlugin.new_schema_validatorr.   r   schema_typer3   r   schema_kindr   configr0   plugin_settingsdict[str, Any]c           	   	   C  s   t   |d}|rd|v r|d }nt j}|dkrdS t|r>t  td|||||td|||||td|||||fS dS )a.  This method is called every time a new `SchemaValidator` is created.

            Args:
                schema: The schema to validate against.
                schema_type: The original type which the schema was created from, e.g. the model class.
                schema_type_path: Path defining where `schema_type` was defined, or where `TypeAdapter` was called.
                schema_kind: The kind of schema to validate against.
                config: The config to use for validation.
                plugin_settings: The plugin settings.

            Returns:
                A tuple of decorator factories for each of the three validation methods -
                    `validate_python`, `validate_json`, `validate_strings` or a tuple of
                    three `None` if recording is `off`.
            r   r'   r   r   validate_pythonvalidate_jsonvalidate_strings)_patch_PluggableSchemaValidatorr8   get_pydantic_plugin_configr'   _include_model_patch_build_wrapperr(   )	r<   r.   r   r3   r   r   r   logfire_settingsr'   r    r    r!   r   7  s   

N)r   r   r   r   r4   r   )r.   r   r   r   r3   r   r   r   r   r0   r   r   r4   r   )r   r   r   r   r   rV   __version__osenvironr8   r   r    r    r    r!   r   !  s
    "
r   )fastapilogfire_backendfastuiztuple[str, ...]IGNORED_MODULESc                 c  s    | ]}| d V  qdS ).Nr    )r   moduler    r    r!   	<genexpr>j  s    r   IGNORED_MODULE_PREFIXESPydanticPlugin | None_pydantic_plugin_config_valuer   c                   C  s   t durt S tjjS )zGet the Pydantic plugin config.N)r   r   param_managerpydantic_pluginr    r    r    r!   r   o  s   r   plugin_configr5   c                 C  s   | a dS )zSet the pydantic plugin config.N)r   )r   r    r    r!   set_pydantic_plugin_configw  s   r   r3   r   rq   c                   sn   t  }|j}|j}j  ts tv rdS |r't fdd|D r'dS |r5t fdd|D S dS )z-Check whether a model should be instrumented.Fc                 3  .    | ]}t | d   dj V  qdS $z::Nresearchnamer   patternr   r3   r    r!   r        , z!_include_model.<locals>.<genexpr>c                 3  r   r   r   r   r   r    r!   r     r   T)r   includeexcluder   
startswithr   r   any)r3   r   r   r   r    r   r!   r   }  s   r   c                  C  s   ddl m}  t| _dS )a%  The old pydantic plugin API required managing state between event handler methods.

    This was messy, especially in a way that handles concurrency and nested validation:
    see https://pydantic.slack.com/archives/C05AF4A4WRM/p1710503400257589.
    The 'new API' simply requires decorating the validation methods, returning a new wrapper function.
    At the time of writing, this API doesn't actually exist yet in pydantic.
    We patch it here so that this will also work for older versions of pydantic without needing to support both APIs.
    r   _schema_validatorN)pydantic.pluginr   _build_wrapperbuild_wrapperr   r    r    r!   r     s   

r   c                  C  s<   ddl m}  t| j d krdd	d
}|| _dS dS )zPatch a 'bug' in PluggableSchemaValidator.

    Getting an attribute before proper initializing (e.g. when using cloudpickle)
    leads to infinite recursion trying to get _schema_validator.
    r   )PluggableSchemaValidatorzg
    def __getattr__(self, name: str) -> Any:
        return getattr(self._schema_validator, name)
    r<   r   r   r:   r4   c                 S  s   |dkrt |t| j|S )Nr   )AttributeErrorgetattrr   )r<   r   r    r    r!   __getattr__  s   z4_patch_PluggableSchemaValidator.<locals>.__getattr__N)r<   r   r   r:   r4   r   )!pydantic.plugin._schema_validatorr   inspect	getsourcer   strip)r   r   r    r    r!   r     s   

	r   PRfuncCallable[P, R]event_handlers	list[Any]c                 C  s2   |D ]}t | |}|r|} qt|r|| } q| S N)_wrap_with_old_handlercallable)r   r   handlerold_wrappedr    r    r!   r     s   
r   r   r   r   c                  O  s   d S r   r    )r   r   r    r    r!   _noop  s   r   r   Callable[P, R] | Nonec                   s   ddl m  t|dt|dt|dt|d  u r/  u r/  u r/tu r0d S  td fdd}|S )Nr   r   on_enter
on_successon_erroron_exceptionrA   P.argsrB   P.kwargsr4   r   c               
     sp   | i | z	| i |}W n!  y! } z|  d }~w t y1 } z|  d }~ww | |S r   )rI   )rA   rB   rM   rN   rO   r   r   r   r   r   r   r    r!   wrapper  s   z'_wrap_with_old_handler.<locals>.wrapper)rA   r   rB   r   r4   r   )rV   r   _get_handler_methodr   rW   rX   )r   r   r   r    r   r!   r     s   



&r   method_nameCallable[..., None]c                 C  s*   t | |d } | d u rtS | jdkrtS | S )Nzpydantic.plugin)r   r   r   )r   r   r    r    r!   r     s   
r   )r.   r   r4   r:   )r4   r   )r   r   r4   r5   )r3   r   r4   rq   )r   r   r   r   r4   r   )r   r   r   r   )r   r   r   r   r4   r   )r   r   r   r:   r4   r   )=r   
__future__r   rW   r   r   r   dataclassesr   r   typingr   r   r   r   r	   r
   rV   typing_extensionsr   r   r   _internal.configr   r   _internal.utilsr   r   r   r   r   pydantic_corer   r   _meter_provider	get_meterMETERcreate_counterrw   r   r   r(   r6   r   pluginr   r   tupler   r   r   r   r   r   r   r   r   r   r   r   r   r    r    r    r!   <module>   sZ     
 
;"D







