Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more specific type for non-callable json_schema_extra #7803

Merged
4 changes: 2 additions & 2 deletions pydantic/_internal/_config.py
Expand Up @@ -17,7 +17,7 @@
Self,
)

from ..config import ConfigDict, ExtraValues, JsonEncoder, JsonSchemaExtraCallable
from ..config import ConfigDict, ExtraValues, JsonDict, JsonEncoder, JsonSchemaExtraCallable
from ..errors import PydanticUserError
from ..warnings import PydanticDeprecatedSince20

Expand Down Expand Up @@ -60,7 +60,7 @@ class ConfigWrapper:
alias_generator: Callable[[str], str] | None
ignored_types: tuple[type, ...]
allow_inf_nan: bool
json_schema_extra: dict[str, object] | JsonSchemaExtraCallable | None
json_schema_extra: JsonDict | JsonSchemaExtraCallable | None
json_encoders: dict[type[object], JsonEncoder] | None

# new in V2
Expand Down
11 changes: 7 additions & 4 deletions pydantic/config.py
@@ -1,7 +1,7 @@
"""Configuration for Pydantic models."""
from __future__ import annotations as _annotations

from typing import TYPE_CHECKING, Any, Callable, Dict, Type, Union
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Type, Union

from typing_extensions import Literal, TypeAlias, TypedDict

Expand All @@ -13,11 +13,14 @@
__all__ = ('ConfigDict',)


JsonValue: TypeAlias = Union[int, float, str, bool, None, List['JsonValue'], 'JsonDict']
JsonDict: TypeAlias = Dict[str, JsonValue]

JsonEncoder = Callable[[Any], Any]

JsonSchemaExtraCallable: TypeAlias = Union[
Callable[[Dict[str, Any]], None],
Callable[[Dict[str, Any], Type[Any]], None],
Callable[[JsonDict], None],
Callable[[JsonDict, Type[Any]], None],
]

ExtraValues = Literal['allow', 'ignore', 'forbid']
Expand Down Expand Up @@ -317,7 +320,7 @@ class without an annotation and has a type that is not in this tuple (or otherwi
allow_inf_nan: bool
"""Whether to allow infinity (`+inf` an `-inf`) and NaN values to float fields. Defaults to `True`."""

json_schema_extra: dict[str, object] | JsonSchemaExtraCallable | None
json_schema_extra: JsonDict | JsonSchemaExtraCallable | None
"""A dict or callable to provide extra JSON schema properties. Defaults to `None`."""

json_encoders: dict[type[object], JsonEncoder] | None
Expand Down
7 changes: 4 additions & 3 deletions pydantic/fields.py
Expand Up @@ -23,6 +23,7 @@

from . import types
from ._internal import _decorators, _fields, _generics, _internal_dataclass, _repr, _typing_extra, _utils
from .config import JsonDict
from .errors import PydanticUserError
from .warnings import PydanticDeprecatedSince20

Expand Down Expand Up @@ -64,7 +65,7 @@ class _FromFieldInfoInputs(typing_extensions.TypedDict, total=False):
decimal_places: int | None
union_mode: Literal['smart', 'left_to_right'] | None
discriminator: str | None
json_schema_extra: dict[str, Any] | typing.Callable[[dict[str, Any]], None] | None
json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None
frozen: bool | None
validate_default: bool | None
repr: bool
Expand Down Expand Up @@ -122,7 +123,7 @@ class FieldInfo(_repr.Representation):
examples: list[Any] | None
exclude: bool | None
discriminator: str | None
json_schema_extra: dict[str, Any] | typing.Callable[[dict[str, Any]], None] | None
json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None
frozen: bool | None
validate_default: bool | None
repr: bool
Expand Down Expand Up @@ -682,7 +683,7 @@ def Field( # noqa: C901
examples: list[Any] | None = _Unset,
exclude: bool | None = _Unset,
discriminator: str | None = _Unset,
json_schema_extra: dict[str, Any] | typing.Callable[[dict[str, Any]], None] | None = _Unset,
json_schema_extra: JsonDict | typing.Callable[[JsonDict], None] | None = _Unset,
frozen: bool | None = _Unset,
validate_default: bool | None = _Unset,
repr: bool = _Unset,
Expand Down
4 changes: 2 additions & 2 deletions pydantic/json_schema.py
Expand Up @@ -50,7 +50,7 @@
_typing_extra,
)
from .annotated_handlers import GetJsonSchemaHandler
from .config import JsonSchemaExtraCallable
from .config import JsonDict, JsonSchemaExtraCallable
from .errors import PydanticInvalidForJsonSchema, PydanticUserError

if TYPE_CHECKING:
Expand Down Expand Up @@ -1338,7 +1338,7 @@ def _update_class_schema(
title: str | None,
extra: Literal['allow', 'ignore', 'forbid'] | None,
cls: type[Any],
json_schema_extra: dict[str, Any] | JsonSchemaExtraCallable | None,
json_schema_extra: JsonDict | JsonSchemaExtraCallable | None,
) -> JsonSchemaValue:
if '$ref' in json_schema:
schema_to_update = self.get_schema_from_definitions(JsonRef(json_schema['$ref'])) or json_schema
Expand Down
3 changes: 0 additions & 3 deletions tests/mypy/test_mypy.py
Expand Up @@ -173,9 +173,6 @@ def test_mypy_results(config_filename: str, python_filename: str, request: pytes
'--show-error-codes',
'--show-traceback',
]
if MYPY_VERSION_TUPLE < (1, 4, 1):
# I don't know exactly what version this got fixed in, but it definitely works in 1.4.1
command.append('--disable-recursive-aliases')
print(f"\nExecuting: mypy {' '.join(command)}") # makes it easier to debug as necessary
mypy_out, mypy_err, mypy_returncode = mypy_api.run(command)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_config.py
Expand Up @@ -23,7 +23,7 @@
)
from pydantic._internal._config import ConfigWrapper, config_defaults
from pydantic._internal._mock_val_ser import MockValSer
from pydantic.config import ConfigDict
from pydantic.config import ConfigDict, JsonValue
from pydantic.dataclasses import dataclass as pydantic_dataclass
from pydantic.errors import PydanticUserError
from pydantic.fields import FieldInfo
Expand Down Expand Up @@ -524,7 +524,7 @@ class Child(Mixin, Parent):

@pytest.mark.skipif(sys.version_info < (3, 10), reason='different on older versions')
def test_config_wrapper_match():
localns = {'_GenerateSchema': GenerateSchema, 'GenerateSchema': GenerateSchema}
localns = {'_GenerateSchema': GenerateSchema, 'GenerateSchema': GenerateSchema, 'JsonValue': JsonValue}
config_dict_annotations = [(k, str(v)) for k, v in get_type_hints(ConfigDict, localns=localns).items()]
config_dict_annotations.sort()
# remove config
Expand Down