
    gK                    r   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rddlmZ ddlmZmZ ddlm Z m!Z! ejD                  jG                  d      Z$e$jK                  d      Z& G d ded      Z' G d ded      Z( G d d      Z)d.dZ*e G d d             Z+ e+       Z,dZ-de.d<    e/d e-D              Z0de.d <   da1d!e.d"<   d/d#Z2d0d$Z3d1d%Z4e	d&        Z5e	d'        Z6 ed(      Z7 ed)      Z8d2d*Z9d3d+Z:d4d,Z;d5d-Z<y)6z.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                      e Zd ZU dZded<   y)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/var/www/openai/venv/lib/python3.12/site-packages/logfire/integrations/pydantic.pyr   r      s     /r#   r   F)totalc                  4    e Zd ZU dZded<   	 ded<   	 ded<   y)	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!    /-
O#00r#   r   c                      e Zd ZdZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZddZddZddZddZ	ddZ
dd	Zdd
ZddZddZy)_ValidateWrapperz2Decorator factory for one schema validator method.)validation_methodschema_name_record_logfirec                   || _         t        |      | _        || _        t        j
                  | _        |j                  di       j                  d      }|r2t        |t              r|g} | j                  j                  | | _        y y )Nr   r)   )r.   get_schema_namer/   r0   r   DEFAULT_LOGFIRE_INSTANCEr1   get
isinstancestr	with_tags)selfr.   schema_config_plugin_settingsschema_type_pathr+   r)   s           r$   __init__z_ValidateWrapper.__init__O   s     "3 +6288
  ##Ir266v>$$v3DMM33T:DM r#   c                <    ddl m  j                  dk(  r"t        j                        d	 fd       }|S  j                  dk(  r"t        j                        d	 fd       }|S  j                  dk(  sJ t        j                        d	 fd       }|S )
zEDecorator which wraps a schema validator method with instrumentation.r   r   allc                   t         j                  s 	| g|i |S j                  |       }	  	| g|i |}j                  d       j	                  ||       |S # $ r*}j                  d       j                  ||        d }~wt        $ r*}j                  d       j                  ||        d }~ww xY wNT)successF)r   _initialized	_on_enter_count_validation_on_success_on_error_span	Exception_on_exception_span)

input_dataargskwargsspanresulterror	exceptionr   r9   	validators
          r$   wrapped_validatorz4_ValidateWrapper.__call__.<locals>.wrapped_validatorq   s    $11 %ZA$A&AA
 ~~j1"&zCDCFCF **4*8$$T62!M ' **5*9''e4  **5*9++D)<s#   A" "C'%BC%B==Cfailurec                @   t         j                  s | g|i |S 	  | g|i |}j                  d       |S # $ r)}j                  d       j                  |        d }~wt        $ r)}j                  d       j                  |        d }~ww xY wrB   )r   rD   rF   _on_error_logrI   _on_exception_log)	rK   rL   rM   rO   rP   rQ   r   r9   rR   s	         r$   rS   z4_ValidateWrapper.__call__.<locals>.wrapped_validator   s    $11$ZA$A&AA"&zCDCFCF **4*8!M ' **5*9&&u-  **5*9**95s!   ? B$A((B4$BBmetricsc                    t         j                  s | g|i |S 	  | g|i |}j                  d       |S # t        $ r j                  d        w xY wrB   )r   rD   rF   rI   )rK   rL   rM   rO   r9   rR   s       r$   rS   z4_ValidateWrapper.__call__.<locals>.wrapped_validator   sw    $11$ZA$A&AA"&zCDCFCF
 **4*8!M ! **5*9s	   ? A)rK   r   rL   r   rM   r   returnr   )pydanticr   r0   	functoolswraps)r9   rR   rS   r   s   `` @r$   __call__z_ValidateWrapper.__call__j   s    , <<5 __Y'" ("H ! Q \\Y& __Y'" ("H ! # <<9,,,__Y'" (" ! r#   c           	         | j                   j                  d| j                  | j                  |dd| j                         j	                         S )Nz*Pydantic {schema_name} {validation_method}infoz	pydantic.)r/   r.   rK   _level
_span_name)r1   rN   r/   r.   	__enter__)r9   rK   s     r$   rE   z_ValidateWrapper._on_enter   sS    }}!!8(("44!"4#9#9":; " 
 )+	r#   c                T    | j                  |dd|       |j                  d d d        y )NT	succeeded)rC   statusrO   )_set_span_attributes__exit__)r9   rN   rO   s      r$   rG   z_ValidateWrapper._on_success   s3    !!	 	" 	
 	dD$'r#   c           	         | j                   j                  dd| j                  |j                         |j	                  d      d       y )Nwarnz"Validation on {schema_name} failedFinclude_url)r/   error_counterrors)levelmsg_template
attributes)r1   logr/   rm   rn   )r9   rP   s     r$   rV   z_ValidateWrapper._on_error_log   sG    =#//$002,,5,9 	 	
r#   c           	         | j                  |dd|j                         |j                  d             |j                  d       |j	                  d d d        y )NFfailedrk   )rC   rf   rm   rn   rj   )rg   rm   rn   	set_levelrh   )r9   rN   rP   s      r$   rH   z_ValidateWrapper._on_error_span   sV    !!))+<<E<2 	" 	
 	vdD$'r#   c                    | j                   j                  dd| j                  t        |      j                  d|       y )NrP   z3Validation on {schema_name} raised {exception_type})r/   exception_type)ro   rp   rq   exc_info)r1   rr   r/   typer   )r9   rQ   s     r$   rW   z"_ValidateWrapper._on_exception_log   s?    N#//"&y/":":  	 	
r#   c                    | j                  |ddt        |      j                          |j                  t        |      ||j                         y )NFzraised )rC   rf   )rg   ry   r   rh   __traceback__)r9   rN   rQ   s      r$   rJ   z#_ValidateWrapper._on_exception_span   sL    !!T)_5567 	" 	

 	d9oy)2I2IJr#   c                   |j                         r.|j                  d|i|       |xj                  d|z   z  c_        y y )NrC    )is_recordingset_attributesmessage)r9   rN   rf   rC   rq   s        r$   rg   z%_ValidateWrapper._set_span_attributes   s=    G Bz BCLLC&L(L r#   c               `    t         j                  d|| j                  | j                  d       y )N   )rC   r/   r.   )validation_counteraddr/   r.   )r9   rC   s     r$   rF   z"_ValidateWrapper._count_validation   s)    743C3CZ^ZpZpq	
r#   N)r.   z?Literal['validate_python', 'validate_json', 'validate_strings']r:   r   r;   CoreConfig | Noner<   zPluginSettings | dict[str, Any]r=   r   r+   r*   rZ   None)rR   r   rZ   r   )rK   r   )rN   r   rO   r   )rP   r   )rN   r   rP   r   )rQ   rI   )rN   r   rQ   rI   )
rN   r   rf   r7   rC   boolrq   r   rZ   r   )rC   r   rZ   r   )r   r   r   r    	__slots__r>   r^   rE   rG   rV   rH   rW   rJ   rg   rF   r"   r#   r$   r-   r-   E   s    <I;Z; ; #	;
 :; ); 5; 
;6L!\(	
	(	
K)

r#   r-   c                   | d   dv r| d   j                   S | d   dv rt        | d         S | d   dk(  rE| d   }|d   dk(  r-|d   }| d   D cg c]  }|d	   |k(  r| c}\  }t        |      S t        |      S | d   S c c}w )
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.
    ry   >   modelr   cls>   function-wrapfunction-afterfunction-beforer:   definitionszdefinition-ref
schema_refref)r   r3   )r:   inner_schemar   
definitionschema_definitions        r$   r3   r3      s     f~//e}%%%	Q	Qvh/00	=	(h'#33*<8J #)"7#"7Je$
2 "7#
 ##455"<00f~#s   A>c                      e Zd ZdZ eej                         ed      k  sej                  j                  d      dk(  r	 	 	 	 	 	 ddZ
y	 	 	 	 	 	 	 	 	 	 	 	 	 	 d	dZ
y)
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offc                     y)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"   )r9   ___s      r$   new_schema_validatorz*LogfirePydanticPlugin.new_schema_validator-  s     $r#   c           
        t                |j                  d      }|r
d|v r|d   }nt               j                  }|dk(  ryt	        |      r9t                t        d|||||      t        d|||||      t        d|||||      fS y)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_PluggableSchemaValidatorr5   get_pydantic_plugin_configr+   _include_model_patch_build_wrapperr-   )	r9   r:   schema_typer=   schema_kindconfigplugin_settingslogfire_settingsr+   s	            r$   r   z*LogfirePydanticPlugin.new_schema_validator7  s    2 ,-.229=H0@$@)(335<<'./$&$%6Yikqr$_ffoWgiop$%7Zjlrs  $r#   N)r   r   r   r   rZ   /tuple[_ValidateWrapper, ...] | tuple[None, ...])r:   r   r   r   r=   r   r   r   r   r   r   zdict[str, Any]rZ   r   )r   r   r   r    r   r[   __version__osenvironr5   r   r"   r#   r$   r   r   !  s     8''(;w+??2::>>RkClpuCu	$	$!$	$<	$,	$,	$ ,	$ -	,	$
 $,	$ &,	$ ,,	$ =,	$r#   r   )fastapilogfire_backendfastuiztuple[str, ...]IGNORED_MODULESc              #  &   K   | ]	  }| d   yw).Nr"   ).0modules     r$   	<genexpr>r   j  s     0\O&F81Os   IGNORED_MODULE_PREFIXESPydanticPlugin | None_pydantic_plugin_config_valuec                 N    t         t         S t        j                  j                  S )zGet the Pydantic plugin config.)r   r   param_managerpydantic_pluginr"   r#   r$   r   r   o  s     $0,,**:::r#   c                    | a y)zSet the pydantic plugin config.N)r   )plugin_configs    r$   set_pydantic_plugin_configr   w  s
     %2!r#   c                     t               }|j                  }|j                  } j                  j	                  t
              st        v ry|rt         fd|D              ry|rt         fd|D              S y)z-Check whether a model should be instrumented.Fc              3  n   K   | ],  }t        j                  | d  dj                          . yw$z::Nresearchnamer   patternr   r=   s     r$   r   z!_include_model.<locals>.<genexpr>  s9     melZaryyG9A6("=M=R=R<S0TUel   25c              3  n   K   | ],  }t        j                  | d  dj                          . ywr   r   r   s     r$   r   z!_include_model.<locals>.<genexpr>  s9     iahV]299y]vhb9I9N9N8O,PQahr   T)r   includeexcluder   
startswithr   r   any)r=   r   r   r   r   s   `   @r$   r   r   }  ss    ')FnnGnnG $$F01V5N 3melmm iahiiir#   c                 &    ddl m}  t        | _        y)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   s    r$   r   r     s     2&4#r#   c                     ddl m}  t        j                  | j                        j                         dj                         k(  rdd}|| _        yy)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)
    c                N    |dk(  rt        |      t        | j                  |      S )Nr   )AttributeErrorgetattrr   )r9   r   s     r$   __getattr__z4_patch_PluggableSchemaValidator.<locals>.__getattr__  s+     **$T**411488r#   N)r9   r   r   r7   rZ   r   )!pydantic.plugin._schema_validatorr   inspect	getsourcer   strip)r   r   s     r$   r   r     sP     K 	2>>?EEG 			9 0; ,#	r#   PRc                ^    |D ]'  }t        | |      }|r|} t        |      s  ||       } ) | S N)_wrap_with_old_handlercallable)funcevent_handlershandlerold_wrappeds       r$   r   r     s:    ! -T7;Dg4=D " Kr#   c                      y r   r"   )r   r   s     r$   _noopr     s    r#   c                     ddl m t        |d      t        |d      t        |d      t        |d      cxu rcxu rcxu rt        u ry  t	        j
                         d fd       }|S )	Nr   r   on_enter
on_successon_erroron_exceptionc                      | i | 	  | i |} 
|       |S # $ r} |        d }~wt         $ r} 	|        d }~ww xY wr   )rI   )rL   rM   rO   rP   rQ   r   r   r   r   r   r   s        r$   wrapperz'_wrap_with_old_handler.<locals>.wrapper  sc    $!&!
	4*6*F vM  	UO 	#	s    A	+A	A  A)rL   zP.argsrM   zP.kwargsrZ   r   )r[   r   _get_handler_methodr   r\   r]   )r   r   r   r   r   r   r   r   s   `  @@@@@r$   r   r     s    ("7J7H$Wl;J"7J7H&w?L:BB\BUB C __T   Nr#   c                Z    t        | |d       } | t        S | j                  dk(  rt        S | S )Nzpydantic.plugin)r   r   r   )r   method_names     r$   r   r     s3    g{D1G			0	0r#   )r:   r   rZ   r7   )rZ   r   )r   r   rZ   r   )r=   r   rZ   r   )r   Callable[P, R]r   z	list[Any]rZ   r   )r   r   r   r   )r   r   r   r   rZ   zCallable[P, R] | None)r   r   r   r7   rZ   zCallable[..., None])=r    
__future__r   r\   r   r   r   dataclassesr   r   typingr   r   r   r	   r
   r   r[   typing_extensionsr   r   r   _internal.configr   r   _internal.utilsr   r   r   r   r   pydantic_corer   r   _meter_provider	get_meterMETERcreate_counterr   r   r   r-   r3   r   pluginr   r!   tupler   r   r   r   r   r   r   r   r   r   r   r   r   r"   r#   r$   <module>r     sN   4 "   	 	 !  L L  '   < )(:4%%//0BC))*@A 0Ye 0(iu $w
 w
tD A$ A$ A$H 
	  $J I+00\O0\+\  \7; 4 ;;2* 5 5 ; ;: cNCL<r#   