8000 Fix url serialization for unions by sydney-runkle · Pull Request #11227 · pydantic/pydantic · GitHub
[go: up one dir, main page]

Skip to content

Fix url serialization for unions #11227

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

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
similar to ip addresses, checking before ser
  • Loading branch information
sydney-runkle committed Jan 7, 2025
commit 3faf897680a5bb742df00d500cc2f329db9af17c
28 changes: 25 additions & 3 deletions pydantic/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network
from typing import TYPE_CHECKING, Any, ClassVar

from pydantic_core import MultiHostHost, PydanticCustomError, SchemaSerializer, core_schema
from pydantic_core import (
MultiHostHost,
PydanticCustomError,
PydanticSerializationUnexpectedValue,
SchemaSerializer,
core_schema,
)
from pydantic_core import MultiHostUrl as _CoreMultiHostUrl
from pydantic_core import Url as _CoreUrl
from typing_extensions import Annotated, Self, TypeAlias
Expand Down Expand Up @@ -283,6 +289,14 @@ def build(
)
)

@classmethod
def serialize_url(cls, url: Any) -> str:
if not isinstance(url, cls):
raise PydanticSerializationUnexpectedValue(
f"Expected `{cls}` but got `{type(url)}` with value `'{url}'` - serialized value may not be as expected."
)
return str(url)

@classmethod
def __get_pydantic_core_schema__(
cls, source: type[_BaseUrl], handler: GetCoreSchemaHandler
Expand All @@ -300,7 +314,7 @@ def wrap_val(v, h):
return core_schema.no_info_wrap_validator_function(
wrap_val,
schema=core_schema.url_schema(**cls._constraints.defined_constraints),
serialization=core_schema.to_string_ser_schema(),
serialization=core_schema.plain_serializer_function_ser_schema(cls.serialize_url),
)

@classmethod
Expand Down Expand Up @@ -450,6 +464,14 @@ def build(
)
)

@classmethod
def serialize_url(cls, url: Any) -> str:
if not isinstance(url, cls):
raise PydanticSerializationUnexpectedValue(
f"Expected `{cls}` but got `{type(url)}` with value `'{url}'` - serialized value may not be as expected."
)
return str(url)

@classmethod
def __get_pydantic_core_schema__(
cls, source: type[_BaseMultiHostUrl], handler: GetCoreSchemaHandler
Expand All @@ -467,7 +489,7 @@ def wrap_val(v, h):
return core_schema.no_info_wrap_validator_function(
wrap_val,
schema=core_schema.multi_host_url_schema(**cls._constraints.defined_constraints),
serialization=core_schema.to_string_ser_schema(),
serialization=core_schema.plain_serializer_function_ser_schema(cls.serialize_url),
)

@classmethod
Expand Down
11 changes: 10 additions & 1 deletion tests/test_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Any, Union

import pytest
from pydantic_core import PydanticCustomError, Url
from pydantic_core import PydanticCustomError, PydanticSerializationError, Url
from typing_extensions import Annotated

from pydantic import (
Expand Down Expand Up @@ -1180,3 +1180,12 @@ class Model(BaseModel):

with pytest.raises(ValidationError, match=r'Value should have at most 45 items after validation'):
Model(postgres='postgres://user:pass@localhost:5432/foobarbazfoo')


def test_unexpected_ser() -> None:
ta = TypeAdapter(HttpUrl)
with pytest.raises(
PydanticSerializationError,
match="Expected `<class 'pydantic.networks.HttpUrl'>` but got `<class 'str'>` with value `'http://example.com'`",
):
ta.dump_python('http://example.com', warnings='error')
Loading
0