Coverage for /pythoncovmergedfiles/medio/medio/src/pydantic/pydantic/_internal/_validate_call.py: 42%
45 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-27 07:38 +0000
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-27 07:38 +0000
1from __future__ import annotations as _annotations
3import inspect
4from dataclasses import dataclass
5from functools import partial
6from typing import Any, Callable
8import pydantic_core
10from ..config import ConfigDict
11from . import _generate_schema, _typing_extra
12from ._config import ConfigWrapper
15@dataclass
16class CallMarker:
17 function: Callable[..., Any]
18 validate_return: bool
21class ValidateCallWrapper:
22 """
23 This is a wrapper around a function that validates the arguments passed to it, and optionally the return value.
25 It's partially inspired by `wraps` which in turn uses `partial`, but extended to be a descriptor so
26 these functions can be applied to instance methods, class methods, static methods, as well as normal functions.
27 """
29 __slots__ = (
30 'raw_function',
31 '_config',
32 '_validate_return',
33 '__pydantic_core_schema__',
34 '__pydantic_validator__',
35 '__signature__',
36 '__name__',
37 '__qualname__',
38 '__annotations__',
39 '__dict__', # required for __module__
40 )
42 def __init__(self, function: Callable[..., Any], config: ConfigDict | None, validate_return: bool):
43 self.raw_function = function
44 self._config = config
45 self._validate_return = validate_return
46 self.__signature__ = inspect.signature(function)
47 if isinstance(function, partial):
48 func = function.func
49 self.__name__ = f'partial({func.__name__})'
50 self.__qualname__ = f'partial({func.__qualname__})'
51 self.__annotations__ = func.__annotations__
52 self.__module__ = func.__module__
53 self.__doc__ = func.__doc__
54 else:
55 self.__name__ = function.__name__
56 self.__qualname__ = function.__qualname__
57 self.__annotations__ = function.__annotations__
58 self.__module__ = function.__module__
59 self.__doc__ = function.__doc__
61 namespace = _typing_extra.add_module_globals(function, None)
62 config_wrapper = ConfigWrapper(config)
63 gen_schema = _generate_schema.GenerateSchema(config_wrapper, namespace)
64 self.__pydantic_core_schema__ = schema = gen_schema.generate_schema(function)
65 core_config = config_wrapper.core_config(self)
66 self.__pydantic_validator__ = pydantic_core.SchemaValidator(schema, core_config)
68 def __call__(self, *args: Any, **kwargs: Any) -> Any:
69 return self.__pydantic_validator__.validate_python(pydantic_core.ArgsKwargs(args, kwargs))
71 def __get__(self, obj: Any, objtype: type[Any] | None = None) -> ValidateCallWrapper:
72 """
73 Bind the raw function and return another ValidateCallWrapper wrapping that.
74 """
75 bound_function = self.raw_function.__get__(obj, objtype)
76 return self.__class__(bound_function, self._config, self._validate_return)
78 def __repr__(self) -> str:
79 return f'ValidateCallWrapper({self.raw_function})'