Skip to content

Commit

Permalink
Add more specific type for non-callable json_schema_extra (#7803)
Browse files Browse the repository at this point in the history
Co-authored-by: Vlad Nedelcu <nedelcuvd@gmail.com>
Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
  • Loading branch information
3 people committed Oct 12, 2023
1 parent 3f2aaa6 commit b2e7ee3
Show file tree
Hide file tree
Showing 6 changed files with 17 additions and 16 deletions.
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

0 comments on commit b2e7ee3

Please sign in to comment.