Skip to content

Commit c1c27d4

Browse files
authored
reconcile _pydantic_core.pyi against the Rust implementation (#701)
1 parent 95955d7 commit c1c27d4

File tree

7 files changed

+79
-79
lines changed

7 files changed

+79
-79
lines changed

pydantic_core/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
PydanticSerializationError,
1111
PydanticSerializationUnexpectedValue,
1212
PydanticUndefined,
13+
PydanticUndefinedType,
1314
SchemaError,
1415
SchemaSerializer,
1516
SchemaValidator,

pydantic_core/_pydantic_core.pyi

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import decimal
22
import sys
3-
from typing import Any, Callable, Generic
4-
5-
from typing_extensions import TypeVar
3+
from typing import Any, Callable, Generic, TypeVar
64

75
from pydantic_core import ErrorDetails, InitErrorDetails
86
from pydantic_core.core_schema import CoreConfig, CoreSchema, ErrorType
@@ -46,25 +44,25 @@ class Some(Generic[T]):
4644
def value(self) -> T: ...
4745

4846
class SchemaValidator:
47+
def __init__(self, schema: CoreSchema, config: 'CoreConfig | None' = None) -> None: ...
4948
@property
5049
def title(self) -> str: ...
51-
def __init__(self, schema: CoreSchema, config: 'CoreConfig | None' = None) -> None: ...
5250
def validate_python(
5351
self,
5452
input: Any,
5553
*,
5654
strict: 'bool | None' = None,
57-
context: Any = None,
5855
from_attributes: 'bool | None' = None,
56+
context: Any = None,
5957
self_instance: 'Any | None' = None,
6058
) -> Any: ...
6159
def isinstance_python(
6260
self,
6361
input: Any,
6462
*,
6563
strict: 'bool | None' = None,
66-
context: Any = None,
6764
from_attributes: 'bool | None' = None,
65+
context: Any = None,
6866
self_instance: 'Any | None' = None,
6967
) -> bool: ...
7068
def validate_json(
@@ -78,12 +76,12 @@ class SchemaValidator:
7876
def validate_assignment(
7977
self,
8078
obj: Any,
81-
field: str,
82-
input: Any,
79+
field_name: str,
80+
field_value: Any,
8381
*,
8482
strict: 'bool | None' = None,
85-
context: Any = None,
8683
from_attributes: 'bool | None' = None,
84+
context: Any = None,
8785
) -> 'dict[str, Any]': ...
8886
def get_default_value(self, *, strict: 'bool | None' = None, context: Any = None) -> Some | None: ...
8987

@@ -151,6 +149,7 @@ def to_jsonable_python(
151149
) -> Any: ...
152150

153151
class Url(SupportsAllComparisons):
152+
def __init__(self, url: str) -> None: ...
154153
@property
155154
def scheme(self) -> str: ...
156155
@property
@@ -167,20 +166,20 @@ class Url(SupportsAllComparisons):
167166
def query(self) -> 'str | None': ...
168167
@property
169168
def fragment(self) -> 'str | None': ...
170-
def __init__(self, url: str) -> None: ...
171169
def unicode_host(self) -> 'str | None': ...
172170
def query_params(self) -> 'list[tuple[str, str]]': ...
173171
def unicode_string(self) -> str: ...
174-
def __str__(self) -> str: ...
175172
def __repr__(self) -> str: ...
173+
def __str__(self) -> str: ...
176174

177175
class MultiHostHost(TypedDict):
178-
scheme: str
179-
path: 'str | None'
180-
query: 'str | None'
181-
fragment: 'str | None'
176+
username: 'str | None'
177+
password: 'str | None'
178+
host: 'str | None'
179+
port: 'int | None'
182180

183181
class MultiHostUrl(SupportsAllComparisons):
182+
def __init__(self, url: str) -> None: ...
184183
@property
185184
def scheme(self) -> str: ...
186185
@property
@@ -189,12 +188,11 @@ class MultiHostUrl(SupportsAllComparisons):
189188
def query(self) -> 'str | None': ...
190189
@property
191190
def fragment(self) -> 'str | None': ...
192-
def __init__(self, url: str) -> None: ...
193191
def hosts(self) -> 'list[MultiHostHost]': ...
194192
def query_params(self) -> 'list[tuple[str, str]]': ...
195193
def unicode_string(self) -> str: ...
196-
def __str__(self) -> str: ...
197194
def __repr__(self) -> str: ...
195+
def __str__(self) -> str: ...
198196

199197
class SchemaError(Exception):
200198
def error_count(self) -> int: ...
@@ -218,29 +216,30 @@ class ValidationError(ValueError):
218216
def title(self) -> str: ...
219217
def error_count(self) -> int: ...
220218
def errors(self, *, include_url: bool = True, include_context: bool = True) -> 'list[ErrorDetails]': ...
221-
def json(self, *, indent: 'int | None' = None, include_url: bool = True, include_context: bool = False) -> str: ...
219+
def json(self, *, indent: 'int | None' = None, include_url: bool = True, include_context: bool = True) -> str: ...
222220

223221
class PydanticCustomError(ValueError):
224222
def __init__(
225223
self, error_type: LiteralString, message_template: LiteralString, context: 'dict[str, Any] | None' = None
226224
) -> None: ...
227225
@property
226+
def context(self) -> 'dict[str, Any] | None': ...
227+
@property
228228
def type(self) -> str: ...
229229
@property
230230
def message_template(self) -> str: ...
231-
context: 'dict[str, Any] | None'
232231
def message(self) -> str: ...
233232

234233
class PydanticKnownError(ValueError):
234+
def __init__(
235+
self, error_type: ErrorType, context: 'dict[str, str | int | float | decimal.Decimal] | None' = None
236+
) -> None: ...
237+
@property
238+
def context(self) -> 'dict[str, str | int | float] | None': ...
235239
@property
236240
def type(self) -> ErrorType: ...
237241
@property
238242
def message_template(self) -> str: ...
239-
context: 'dict[str, str | int | float] | None'
240-
241-
def __init__(
242-
self, error_type: ErrorType, context: 'dict[str, str | int | float | decimal.Decimal] | None' = None
243-
) -> None: ...
244243
def message(self) -> str: ...
245244

246245
class PydanticOmit(Exception):

src/errors/types.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ pub enum ErrorMode {
2020
Json,
2121
}
2222

23-
impl TryFrom<Option<&str>> for ErrorMode {
23+
impl TryFrom<&str> for ErrorMode {
2424
type Error = PyErr;
2525

26-
fn try_from(error_mode: Option<&str>) -> PyResult<Self> {
26+
fn try_from(error_mode: &str) -> PyResult<Self> {
2727
match error_mode {
28-
None => Ok(Self::Python),
29-
Some("python") => Ok(Self::Python),
30-
Some("json") => Ok(Self::Json),
31-
Some(s) => py_err!(PyValueError; "Invalid error mode: {}", s),
28+
"python" => Ok(Self::Python),
29+
"json" => Ok(Self::Json),
30+
s => py_err!(PyValueError; "Invalid error mode: {}", s),
3231
}
3332
}
3433
}

src/errors/validation_exception.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,12 @@ impl<'a> IntoPy<ValError<'a>> for ValidationError {
128128
#[pymethods]
129129
impl ValidationError {
130130
#[staticmethod]
131-
#[pyo3(signature = (title, line_errors, error_mode=None, hide_input=false))]
131+
#[pyo3(signature = (title, line_errors, error_mode="python", hide_input=false))]
132132
fn from_exception_data(
133133
py: Python,
134134
title: PyObject,
135135
line_errors: &PyList,
136-
error_mode: Option<&str>,
136+
error_mode: &str,
137137
hide_input: bool,
138138
) -> PyResult<Py<Self>> {
139139
Py::new(
@@ -186,7 +186,7 @@ impl ValidationError {
186186
include_url: bool,
187187
include_context: bool,
188188
) -> PyResult<&'py PyString> {
189-
let state = SerializationState::new(None, None);
189+
let state = SerializationState::new("iso8601", "utf8")?;
190190
let extra = state.extra(py, &SerMode::Json, true, false, false, true, None);
191191
let serializer = ValidationErrorSerializer {
192192
py,

src/serializers/config.rs

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::borrow::Cow;
2-
use std::str::{from_utf8, Utf8Error};
2+
use std::str::{from_utf8, FromStr, Utf8Error};
33

44
use pyo3::prelude::*;
55
use pyo3::types::{PyDelta, PyDict};
@@ -29,42 +29,42 @@ impl SerializationConfig {
2929
})
3030
}
3131

32-
pub fn from_args(timedelta_mode: Option<&str>, bytes_mode: Option<&str>) -> PyResult<Self> {
33-
let timedelta_mode = TimedeltaMode::from_str(timedelta_mode)?;
34-
let bytes_mode = BytesMode::from_str(bytes_mode)?;
32+
pub fn from_args(timedelta_mode: &str, bytes_mode: &str) -> PyResult<Self> {
3533
Ok(Self {
36-
timedelta_mode,
37-
bytes_mode,
34+
timedelta_mode: TimedeltaMode::from_str(timedelta_mode)?,
35+
bytes_mode: BytesMode::from_str(bytes_mode)?,
3836
})
3937
}
4038
}
4139

42-
#[derive(Debug, Clone)]
40+
#[derive(Default, Debug, Clone)]
4341
pub(crate) enum TimedeltaMode {
42+
#[default]
4443
Iso8601,
4544
Float,
4645
}
4746

48-
impl TimedeltaMode {
49-
pub fn from_config(config: Option<&PyDict>) -> PyResult<Self> {
50-
let raw_mode: Option<&str> = match config {
51-
Some(c) => c.get_as::<&str>(intern!(c.py(), "ser_json_timedelta"))?,
52-
None => None,
53-
};
54-
Self::from_str(raw_mode)
55-
}
47+
impl FromStr for TimedeltaMode {
48+
type Err = PyErr;
5649

57-
pub fn from_str(s: Option<&str>) -> PyResult<Self> {
50+
fn from_str(s: &str) -> Result<Self, Self::Err> {
5851
match s {
59-
Some("iso8601") => Ok(Self::Iso8601),
60-
Some("float") => Ok(Self::Float),
61-
Some(s) => py_schema_err!(
52+
"iso8601" => Ok(Self::Iso8601),
53+
"float" => Ok(Self::Float),
54+
s => py_schema_err!(
6255
"Invalid timedelta serialization mode: `{}`, expected `iso8601` or `float`",
6356
s
6457
),
65-
None => Ok(Self::Iso8601),
6658
}
6759
}
60+
}
61+
62+
impl TimedeltaMode {
63+
pub fn from_config(config: Option<&PyDict>) -> PyResult<Self> {
64+
let Some(config_dict) = config else { return Ok(Self::default()) };
65+
let raw_mode = config_dict.get_as::<&str>(intern!(config_dict.py(), "ser_json_timedelta"))?;
66+
raw_mode.map_or_else(|| Ok(Self::default()), Self::from_str)
67+
}
6868

6969
fn total_seconds(py_timedelta: &PyDelta) -> PyResult<&PyAny> {
7070
py_timedelta.call_method0(intern!(py_timedelta.py(), "total_seconds"))
@@ -116,29 +116,30 @@ impl TimedeltaMode {
116116
}
117117
}
118118

119-
#[derive(Debug, Clone)]
119+
#[derive(Default, Debug, Clone)]
120120
pub(crate) struct BytesMode {
121121
base64_config: Option<base64::Config>,
122122
}
123123

124-
impl BytesMode {
125-
pub fn from_config(config: Option<&PyDict>) -> PyResult<Self> {
126-
let raw_mode: Option<&str> = match config {
127-
Some(c) => c.get_as::<&str>(intern!(c.py(), "ser_json_bytes"))?,
128-
None => None,
129-
};
130-
Self::from_str(raw_mode)
131-
}
124+
impl FromStr for BytesMode {
125+
type Err = PyErr;
132126

133-
pub fn from_str(s: Option<&str>) -> PyResult<Self> {
127+
fn from_str(s: &str) -> Result<Self, Self::Err> {
134128
let base64_config = match s {
135-
Some("utf8") => None,
136-
Some("base64") => Some(base64::Config::new(base64::CharacterSet::UrlSafe, true)),
137-
Some(s) => return py_schema_err!("Invalid bytes serialization mode: `{}`, expected `utf8` or `base64`", s),
138-
None => None,
129+
"utf8" => None,
130+
"base64" => Some(base64::Config::new(base64::CharacterSet::UrlSafe, true)),
131+
s => return py_schema_err!("Invalid bytes serialization mode: `{}`, expected `utf8` or `base64`", s),
139132
};
140133
Ok(Self { base64_config })
141134
}
135+
}
136+
137+
impl BytesMode {
138+
pub fn from_config(config: Option<&PyDict>) -> PyResult<Self> {
139+
let Some(config_dict) = config else { return Ok(Self::default()) };
140+
let raw_mode = config_dict.get_as::<&str>(intern!(config_dict.py(), "ser_json_bytes"))?;
141+
raw_mode.map_or_else(|| Ok(Self::default()), Self::from_str)
142+
}
142143

143144
pub fn bytes_to_string<'py>(&self, py: Python, bytes: &'py [u8]) -> PyResult<Cow<'py, str>> {
144145
if let Some(config) = self.base64_config {

src/serializers/extra.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ pub(crate) struct SerializationState {
2323
}
2424

2525
impl SerializationState {
26-
pub fn new(timedelta_mode: Option<&str>, bytes_mode: Option<&str>) -> Self {
26+
pub fn new(timedelta_mode: &str, bytes_mode: &str) -> PyResult<Self> {
2727
let warnings = CollectWarnings::new(false);
2828
let rec_guard = SerRecursionGuard::default();
29-
let config = SerializationConfig::from_args(timedelta_mode, bytes_mode).unwrap();
30-
Self {
29+
let config = SerializationConfig::from_args(timedelta_mode, bytes_mode)?;
30+
Ok(Self {
3131
warnings,
3232
rec_guard,
3333
config,
34-
}
34+
})
3535
}
3636

3737
#[allow(clippy::too_many_arguments)]

src/serializers/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ impl SchemaSerializer {
202202
#[allow(clippy::too_many_arguments)]
203203
#[pyfunction]
204204
#[pyo3(signature = (value, *, indent = None, include = None, exclude = None, by_alias = true,
205-
exclude_none = false, round_trip = false, timedelta_mode = None, bytes_mode = None,
205+
exclude_none = false, round_trip = false, timedelta_mode = "iso8601", bytes_mode = "utf8",
206206
serialize_unknown = false, fallback = None))]
207207
pub fn to_json(
208208
py: Python,
@@ -213,12 +213,12 @@ pub fn to_json(
213213
by_alias: bool,
214214
exclude_none: bool,
215215
round_trip: bool,
216-
timedelta_mode: Option<&str>,
217-
bytes_mode: Option<&str>,
216+
timedelta_mode: &str,
217+
bytes_mode: &str,
218218
serialize_unknown: bool,
219219
fallback: Option<&PyAny>,
220220
) -> PyResult<PyObject> {
221-
let state = SerializationState::new(timedelta_mode, bytes_mode);
221+
let state = SerializationState::new(timedelta_mode, bytes_mode)?;
222222
let extra = state.extra(
223223
py,
224224
&SerMode::Json,
@@ -238,7 +238,7 @@ pub fn to_json(
238238
#[allow(clippy::too_many_arguments)]
239239
#[pyfunction]
240240
#[pyo3(signature = (value, *, include = None, exclude = None, by_alias = true, exclude_none = false, round_trip = false,
241-
timedelta_mode = None, bytes_mode = None, serialize_unknown = false, fallback = None))]
241+
timedelta_mode = "iso8601", bytes_mode = "utf8", serialize_unknown = false, fallback = None))]
242242
pub fn to_jsonable_python(
243243
py: Python,
244244
value: &PyAny,
@@ -247,12 +247,12 @@ pub fn to_jsonable_python(
247247
by_alias: bool,
248248
exclude_none: bool,
249249
round_trip: bool,
250-
timedelta_mode: Option<&str>,
251-
bytes_mode: Option<&str>,
250+
timedelta_mode: &str,
251+
bytes_mode: &str,
252252
serialize_unknown: bool,
253253
fallback: Option<&PyAny>,
254254
) -> PyResult<PyObject> {
255-
let state = SerializationState::new(timedelta_mode, bytes_mode);
255+
let state = SerializationState::new(timedelta_mode, bytes_mode)?;
256256
let extra = state.extra(
257257
py,
258258
&SerMode::Json,

0 commit comments

Comments
 (0)