Skip to content

Commit 400a083

Browse files
davidhewittViicos
andauthored
Add option to preserve empty URL paths (#1789)
Co-authored-by: Victorien <[email protected]>
1 parent ed0d1ca commit 400a083

File tree

7 files changed

+544
-145
lines changed

7 files changed

+544
-145
lines changed

python/pydantic_core/core_schema.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3908,6 +3908,7 @@ def url_schema(
39083908
default_host: str | None = None,
39093909
default_port: int | None = None,
39103910
default_path: str | None = None,
3911+
preserve_empty_path: bool | None = None,
39113912
strict: bool | None = None,
39123913
ref: str | None = None,
39133914
metadata: dict[str, Any] | None = None,
@@ -3932,6 +3933,7 @@ def url_schema(
39323933
default_host: The default host to use if the URL does not have a host
39333934
default_port: The default port to use if the URL does not have a port
39343935
default_path: The default path to use if the URL does not have a path
3936+
preserve_empty_path: Whether to preserve an empty path or convert it to '/', default False
39353937
strict: Whether to use strict URL parsing
39363938
ref: optional unique identifier of the schema, used to reference the schema in other places
39373939
metadata: Any other information you want to include with the schema, not used by pydantic-core
@@ -3945,6 +3947,7 @@ def url_schema(
39453947
default_host=default_host,
39463948
default_port=default_port,
39473949
default_path=default_path,
3950+
preserve_empty_path=preserve_empty_path,
39483951
strict=strict,
39493952
ref=ref,
39503953
metadata=metadata,
@@ -3974,6 +3977,7 @@ def multi_host_url_schema(
39743977
default_host: str | None = None,
39753978
default_port: int | None = None,
39763979
default_path: str | None = None,
3980+
preserve_empty_path: bool | None = None,
39773981
strict: bool | None = None,
39783982
ref: str | None = None,
39793983
metadata: dict[str, Any] | None = None,
@@ -3998,6 +4002,7 @@ def multi_host_url_schema(
39984002
default_host: The default host to use if the URL does not have a host
39994003
default_port: The default port to use if the URL does not have a port
40004004
default_path: The default path to use if the URL does not have a path
4005+
preserve_empty_path: Whether to preserve an empty path or convert it to '/', default False
40014006
strict: Whether to use strict URL parsing
40024007
ref: optional unique identifier of the schema, used to reference the schema in other places
40034008
metadata: Any other information you want to include with the schema, not used by pydantic-core
@@ -4011,6 +4016,7 @@ def multi_host_url_schema(
40114016
default_host=default_host,
40124017
default_port=default_port,
40134018
default_path=default_path,
4019+
preserve_empty_path=preserve_empty_path,
40144020
strict=strict,
40154021
ref=ref,
40164022
metadata=metadata,

src/serializers/infer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,11 @@ pub(crate) fn infer_to_python_known(
197197
}
198198
ObType::Url => {
199199
let py_url: PyUrl = value.extract()?;
200-
py_url.__str__().into_py_any(py)?
200+
py_url.__str__(py).into_py_any(py)?
201201
}
202202
ObType::MultiHostUrl => {
203203
let py_url: PyMultiHostUrl = value.extract()?;
204-
py_url.__str__().into_py_any(py)?
204+
py_url.__str__(py).into_py_any(py)?
205205
}
206206
ObType::Uuid => {
207207
let uuid = super::type_serializers::uuid::uuid_to_string(value)?;
@@ -476,11 +476,11 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
476476
}
477477
ObType::Url => {
478478
let py_url: PyUrl = value.extract().map_err(py_err_se_err)?;
479-
serializer.serialize_str(py_url.__str__())
479+
serializer.serialize_str(py_url.__str__(value.py()))
480480
}
481481
ObType::MultiHostUrl => {
482482
let py_url: PyMultiHostUrl = value.extract().map_err(py_err_se_err)?;
483-
serializer.serialize_str(&py_url.__str__())
483+
serializer.serialize_str(&py_url.__str__(value.py()))
484484
}
485485
ObType::PydanticSerializable => {
486486
let py = value.py();
@@ -644,11 +644,11 @@ pub(crate) fn infer_json_key_known<'a>(
644644
}
645645
ObType::Url => {
646646
let py_url: PyUrl = key.extract()?;
647-
Ok(Cow::Owned(py_url.__str__().to_string()))
647+
Ok(Cow::Owned(py_url.__str__(key.py()).to_string()))
648648
}
649649
ObType::MultiHostUrl => {
650650
let py_url: PyMultiHostUrl = key.extract()?;
651-
Ok(Cow::Owned(py_url.__str__()))
651+
Ok(Cow::Owned(py_url.__str__(key.py()).to_string()))
652652
}
653653
ObType::Tuple => {
654654
let mut key_build = super::type_serializers::tuple::KeyBuilder::new();

src/serializers/type_serializers/url.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ macro_rules! build_serializer {
4646
let py = value.py();
4747
match value.extract::<$extract>() {
4848
Ok(py_url) => match extra.mode {
49-
SerMode::Json => py_url.__str__().into_py_any(py),
49+
SerMode::Json => py_url.__str__(value.py()).into_py_any(py),
5050
_ => Ok(value.clone().unbind()),
5151
},
5252
Err(_) => {
@@ -58,7 +58,7 @@ macro_rules! build_serializer {
5858

5959
fn json_key<'a>(&self, key: &'a Bound<'_, PyAny>, extra: &Extra) -> PyResult<Cow<'a, str>> {
6060
match key.extract::<$extract>() {
61-
Ok(py_url) => Ok(Cow::Owned(py_url.__str__().to_string())),
61+
Ok(py_url) => Ok(Cow::Owned(py_url.__str__(key.py()).to_string())),
6262
Err(_) => {
6363
extra.warnings.on_fallback_py(self.get_name(), key, extra)?;
6464
infer_json_key(key, extra)
@@ -75,7 +75,7 @@ macro_rules! build_serializer {
7575
extra: &Extra,
7676
) -> Result<S::Ok, S::Error> {
7777
match value.extract::<$extract>() {
78-
Ok(py_url) => serializer.serialize_str(&py_url.__str__()),
78+
Ok(py_url) => serializer.serialize_str(&py_url.__str__(value.py())),
7979
Err(_) => {
8080
extra
8181
.warnings

0 commit comments

Comments
 (0)