|
4 | 4 |
|
5 | 5 | import functools |
6 | 6 | import inspect |
| 7 | +import os |
7 | 8 | import re |
8 | 9 | from dataclasses import dataclass |
9 | 10 | from functools import lru_cache |
10 | 11 | from typing import TYPE_CHECKING, Any, Callable, Literal, TypedDict, TypeVar |
11 | 12 |
|
| 13 | +import pydantic |
12 | 14 | from typing_extensions import ParamSpec |
13 | 15 |
|
14 | 16 | import logfire |
15 | 17 | from logfire import LogfireSpan |
16 | 18 |
|
17 | 19 | from .._internal.config import GLOBAL_CONFIG, PydanticPlugin |
18 | 20 | from .._internal.config_params import default_param_manager |
| 21 | +from .._internal.utils import get_version |
19 | 22 |
|
20 | 23 | if TYPE_CHECKING: # pragma: no cover |
21 | 24 | from pydantic import ValidationError |
22 | | - from pydantic.plugin import ( |
23 | | - SchemaKind, |
24 | | - SchemaTypePath, |
25 | | - ) |
| 25 | + from pydantic.plugin import SchemaKind, SchemaTypePath |
26 | 26 | from pydantic_core import CoreConfig, CoreSchema |
27 | 27 |
|
28 | 28 |
|
@@ -292,61 +292,71 @@ def get_schema_name(schema: CoreSchema) -> str: |
292 | 292 | class LogfirePydanticPlugin: |
293 | 293 | """Implements a new API for pydantic plugins. |
294 | 294 |
|
295 | | - Patches pydantic to accept this new API shape. |
296 | | -
|
297 | | - Set the `LOGFIRE_DISABLE_PYDANTIC_PLUGIN` environment variable to `true` to disable the plugin. |
298 | | -
|
299 | | - Note: |
300 | | - In the future, you'll be able to use the `PYDANTIC_DISABLE_PLUGINS` instead. |
| 295 | + Patches Pydantic to accept this new API shape. |
301 | 296 |
|
302 | | - See [pydantic/pydantic#7709](https://github.com/pydantic/pydantic/issues/7709) for more information. |
| 297 | + Set the `LOGFIRE_PYDANTIC_RECORD` environment variable to `"off"` to disable the plugin, or |
| 298 | + `PYDANTIC_DISABLE_PLUGINS` to `true` to disable all Pydantic plugins. |
303 | 299 | """ |
304 | 300 |
|
305 | | - def new_schema_validator( |
306 | | - self, |
307 | | - schema: CoreSchema, |
308 | | - schema_type: Any, |
309 | | - schema_type_path: SchemaTypePath, |
310 | | - schema_kind: SchemaKind, |
311 | | - config: CoreConfig | None, |
312 | | - plugin_settings: dict[str, Any], |
313 | | - ) -> tuple[_ValidateWrapper, ...] | tuple[None, ...]: |
314 | | - """This method is called every time a new `SchemaValidator` is created. |
315 | | -
|
316 | | - Args: |
317 | | - schema: The schema to validate against. |
318 | | - schema_type: The original type which the schema was created from, e.g. the model class. |
319 | | - schema_type_path: Path defining where `schema_type` was defined, or where `TypeAdapter` was called. |
320 | | - schema_kind: The kind of schema to validate against. |
321 | | - config: The config to use for validation. |
322 | | - plugin_settings: The plugin settings. |
323 | | -
|
324 | | - Returns: |
325 | | - A tuple of decorator factories for each of the three validation methods - |
326 | | - `validate_python`, `validate_json`, `validate_strings` or a tuple of |
327 | | - three `None` if recording is `off`. |
328 | | - """ |
329 | | - # Patch a bug that occurs even if the plugin is disabled. |
330 | | - _patch_PluggableSchemaValidator() |
331 | | - |
332 | | - logfire_settings = plugin_settings.get('logfire') |
333 | | - if logfire_settings and 'record' in logfire_settings: |
334 | | - record = logfire_settings['record'] |
335 | | - else: |
336 | | - record = _pydantic_plugin_config().record |
| 301 | + if ( |
| 302 | + get_version(pydantic.__version__) < get_version('2.5.0') or os.environ.get('LOGFIRE_PYDANTIC_RECORD') == 'off' |
| 303 | + ): # pragma: no cover |
| 304 | + |
| 305 | + def new_schema_validator( # type: ignore[reportRedeclaration] |
| 306 | + self, *_: Any, **__: Any |
| 307 | + ) -> tuple[_ValidateWrapper, ...] | tuple[None, ...]: |
| 308 | + """Backwards compatibility for Pydantic < 2.5.0. |
337 | 309 |
|
338 | | - if record == 'off': |
| 310 | + This method is called every time a new `SchemaValidator` is created, and is a NO-OP for Pydantic < 2.5.0. |
| 311 | + """ |
339 | 312 | return None, None, None |
| 313 | + else: |
340 | 314 |
|
341 | | - if _include_model(schema_type_path): |
342 | | - _patch_build_wrapper() |
343 | | - return ( |
344 | | - _ValidateWrapper('validate_python', schema, config, plugin_settings, schema_type_path, record), |
345 | | - _ValidateWrapper('validate_json', schema, config, plugin_settings, schema_type_path, record), |
346 | | - _ValidateWrapper('validate_strings', schema, config, plugin_settings, schema_type_path, record), |
347 | | - ) |
| 315 | + def new_schema_validator( |
| 316 | + self, |
| 317 | + schema: CoreSchema, |
| 318 | + schema_type: Any, |
| 319 | + schema_type_path: SchemaTypePath, |
| 320 | + schema_kind: SchemaKind, |
| 321 | + config: CoreConfig | None, |
| 322 | + plugin_settings: dict[str, Any], |
| 323 | + ) -> tuple[_ValidateWrapper, ...] | tuple[None, ...]: |
| 324 | + """This method is called every time a new `SchemaValidator` is created. |
| 325 | +
|
| 326 | + Args: |
| 327 | + schema: The schema to validate against. |
| 328 | + schema_type: The original type which the schema was created from, e.g. the model class. |
| 329 | + schema_type_path: Path defining where `schema_type` was defined, or where `TypeAdapter` was called. |
| 330 | + schema_kind: The kind of schema to validate against. |
| 331 | + config: The config to use for validation. |
| 332 | + plugin_settings: The plugin settings. |
| 333 | +
|
| 334 | + Returns: |
| 335 | + A tuple of decorator factories for each of the three validation methods - |
| 336 | + `validate_python`, `validate_json`, `validate_strings` or a tuple of |
| 337 | + three `None` if recording is `off`. |
| 338 | + """ |
| 339 | + # Patch a bug that occurs even if the plugin is disabled. |
| 340 | + _patch_PluggableSchemaValidator() |
| 341 | + |
| 342 | + logfire_settings = plugin_settings.get('logfire') |
| 343 | + if logfire_settings and 'record' in logfire_settings: |
| 344 | + record = logfire_settings['record'] |
| 345 | + else: |
| 346 | + record = _pydantic_plugin_config().record |
| 347 | + |
| 348 | + if record == 'off': |
| 349 | + return None, None, None |
| 350 | + |
| 351 | + if _include_model(schema_type_path): |
| 352 | + _patch_build_wrapper() |
| 353 | + return ( |
| 354 | + _ValidateWrapper('validate_python', schema, config, plugin_settings, schema_type_path, record), |
| 355 | + _ValidateWrapper('validate_json', schema, config, plugin_settings, schema_type_path, record), |
| 356 | + _ValidateWrapper('validate_strings', schema, config, plugin_settings, schema_type_path, record), |
| 357 | + ) |
348 | 358 |
|
349 | | - return None, None, None |
| 359 | + return None, None, None |
350 | 360 |
|
351 | 361 |
|
352 | 362 | plugin = LogfirePydanticPlugin() |
|
0 commit comments