Skip to content

Commit

Permalink
Address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
hramezani committed Oct 26, 2023
1 parent 50a30c0 commit e6b0504
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 76 deletions.
14 changes: 11 additions & 3 deletions docs/concepts/plugins.md
Expand Up @@ -58,10 +58,12 @@ Let's see an example of a plugin that _wraps_ the `validate_python` method of th
from typing import Any, Dict, Optional, Union

from pydantic_core import CoreConfig, CoreSchema, ValidationError
from typing_extensions import Literal

from pydantic.plugin import (
NewSchemaReturns,
PydanticPluginProtocol,
SchemaTypePath,
ValidatePythonHandlerProtocol,
)

Expand Down Expand Up @@ -89,9 +91,15 @@ class Plugin(PydanticPluginProtocol):
def new_schema_validator(
self,
schema: CoreSchema,
source_type: str,
type_path: str,
item_type: str,
schema_type: str,
schema_type_path: SchemaTypePath,
schema_kind: Literal[
'BaseModel',
'TypeAdapter',
'dataclass',
'create_model',
'validate_call',
],
config: Union[CoreConfig, None],
plugin_settings: Dict[str, object],
) -> NewSchemaReturns:
Expand Down
8 changes: 4 additions & 4 deletions pydantic/_internal/_validate_call.py
Expand Up @@ -46,14 +46,14 @@ def __init__(self, function: Callable[..., Any], config: ConfigDict | None, vali
self.__signature__ = inspect.signature(function)
if isinstance(function, partial):
func = function.func
source_type = func
schema_type = func
self.__name__ = f'partial({func.__name__})'
self.__qualname__ = f'partial({func.__qualname__})'
self.__annotations__ = func.__annotations__
self.__module__ = func.__module__
self.__doc__ = func.__doc__
else:
source_type = function
schema_type = function
self.__name__ = function.__name__
self.__qualname__ = function.__qualname__
self.__annotations__ = function.__annotations__
Expand All @@ -69,7 +69,7 @@ def __init__(self, function: Callable[..., Any], config: ConfigDict | None, vali

self.__pydantic_validator__ = create_schema_validator(
schema,
source_type,
schema_type,
self.__module__,
self.__qualname__,
'validate_call',
Expand All @@ -88,7 +88,7 @@ def __init__(self, function: Callable[..., Any], config: ConfigDict | None, vali
self.__return_pydantic_core_schema__ = schema
validator = create_schema_validator(
schema,
source_type,
schema_type,
self.__module__,
self.__qualname__,
'validate_call',
Expand Down
21 changes: 13 additions & 8 deletions pydantic/plugin/__init__.py
Expand Up @@ -4,10 +4,10 @@
"""
from __future__ import annotations

from typing import Any, Callable
from typing import Any, Callable, NamedTuple

from pydantic_core import CoreConfig, CoreSchema, ValidationError
from typing_extensions import Protocol, TypeAlias
from typing_extensions import Literal, Protocol, TypeAlias

__all__ = (
'PydanticPluginProtocol',
Expand All @@ -21,15 +21,20 @@
NewSchemaReturns: TypeAlias = 'tuple[ValidatePythonHandlerProtocol | None, ValidateJsonHandlerProtocol | None, ValidateStringsHandlerProtocol | None]'


class SchemaTypePath(NamedTuple):
module: str
name: str


class PydanticPluginProtocol(Protocol):
"""Protocol defining the interface for Pydantic plugins."""

def new_schema_validator(
self,
schema: CoreSchema,
source_type: str,
type_path: str,
item_type: str,
schema_type: Any,
schema_type_path: SchemaTypePath,
schema_kind: Literal['BaseModel', 'TypeAdapter', 'dataclass', 'create_model', 'validate_call'],
config: CoreConfig | None,
plugin_settings: dict[str, object],
) -> tuple[
Expand All @@ -43,9 +48,9 @@ def new_schema_validator(
Args:
schema: The schema to validate against.
source_type: The item to validate against.
type_path: The path of item to validate against.
item_type: The type of item to validate against.
schema_type: The schema to validate against.
schema_type_path: The path of schema to validate against.
schema_kind: The kind of schema to validate against.
config: The config to use for validation.
plugin_settings: Any plugin settings.
Expand Down
27 changes: 13 additions & 14 deletions pydantic/plugin/_schema_validator.py
Expand Up @@ -7,6 +7,8 @@
from pydantic_core import CoreConfig, CoreSchema, SchemaValidator, ValidationError
from typing_extensions import Literal, ParamSpec

from pydantic.plugin import SchemaTypePath

if TYPE_CHECKING:
from . import BaseValidateHandlerProtocol, PydanticPluginProtocol

Expand All @@ -17,16 +19,12 @@
events: list[Event] = list(Event.__args__) # type: ignore


def build_type_path(module: str, name: str) -> str:
return f'{module}:{name}'


def create_schema_validator(
schema: CoreSchema,
source_type: Any,
module: str,
type_name: str,
item_type: str,
schema_type: Any,
schema_type_module: str,
schema_type_name: str,
schema_kind: Literal['BaseModel', 'TypeAdapter', 'dataclass', 'create_model', 'validate_call'],
config: CoreConfig | None = None,
plugin_settings: dict[str, Any] | None = None,
) -> SchemaValidator:
Expand All @@ -39,8 +37,7 @@ def create_schema_validator(

plugins = get_plugins()
if plugins:
type_path = build_type_path(module, type_name)
return PluggableSchemaValidator(schema, source_type, type_path, item_type, config, plugins, plugin_settings or {}) # type: ignore
return PluggableSchemaValidator(schema, schema_type, SchemaTypePath(schema_type_module, schema_type_name), schema_kind, config, plugins, plugin_settings or {}) # type: ignore
else:
return SchemaValidator(schema, config)

Expand All @@ -53,9 +50,9 @@ class PluggableSchemaValidator:
def __init__(
self,
schema: CoreSchema,
source_type: Any,
type_path: str,
item_type: str,
schema_type: Any,
schema_type_path: SchemaTypePath,
schema_kind: Literal['BaseModel', 'TypeAdapter', 'dataclass', 'create_model', 'validate_call'],
config: CoreConfig | None,
plugins: Iterable[PydanticPluginProtocol],
plugin_settings: dict[str, Any],
Expand All @@ -66,7 +63,9 @@ def __init__(
json_event_handlers: list[BaseValidateHandlerProtocol] = []
strings_event_handlers: list[BaseValidateHandlerProtocol] = []
for plugin in plugins:
p, j, s = plugin.new_schema_validator(schema, source_type, type_path, item_type, config, plugin_settings)
p, j, s = plugin.new_schema_validator(
schema, schema_type, schema_type_path, schema_kind, config, plugin_settings
)
if p is not None:
python_event_handlers.append(p)
if j is not None:
Expand Down
8 changes: 5 additions & 3 deletions pydantic/type_adapter.py
Expand Up @@ -219,14 +219,16 @@ def __init__(
) -> None:
...

def __init__(self, type: Any, *, config: ConfigDict | None = None, _parent_depth: int = 2, module: str | None = None) -> None:
def __init__(
self, type: Any, *, config: ConfigDict | None = None, _parent_depth: int = 2, module: str | None = None
) -> None:
"""Initializes the TypeAdapter object.
Args:
type: The type associated with the `TypeAdapter`.
config: Configuration for the `TypeAdapter`, should be a dictionary conforming to [`ConfigDict`][pydantic.config.ConfigDict].
_parent_depth: depth at which to search the parent namespace to construct the local namespace.
module: The module that passes to plugin if provided.
!!! note
You cannot use the `config` argument when instantiating a `TypeAdapter` if the type you're using has its own
Expand Down Expand Up @@ -272,7 +274,7 @@ def __init__(self, type: Any, *, config: ConfigDict | None = None, _parent_depth
if module is None:
f = sys._getframe(1)
module = f.f_globals['__name__']
validator = create_schema_validator(core_schema, type, module, str(type), 'type_adapter', core_config, config_wrapper.plugin_settings) # type: ignore
validator = create_schema_validator(core_schema, type, module, str(type), 'TypeAdapter', core_config, config_wrapper.plugin_settings) # type: ignore

serializer: SchemaSerializer
try:
Expand Down
2 changes: 1 addition & 1 deletion tests/plugin/example_plugin.py
Expand Up @@ -24,7 +24,7 @@ def on_error(self, error) -> None:


class Plugin:
def new_schema_validator(self, schema, source_type, type_path, item_type, config, plugin_settings):
def new_schema_validator(self, schema, schema_type, schema_type_path, schema_kind, config, plugin_settings):
return ValidatePythonHandler(), None, None


Expand Down

0 comments on commit e6b0504

Please sign in to comment.