Skip to content

Commit 66b0196

Browse files
committed
adding tools.rs, associated cleanup
1 parent 26fa27d commit 66b0196

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+286
-222
lines changed

src/argument_markers.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
use crate::tools::safe_repr;
12
use pyo3::basic::CompareOp;
23
use pyo3::prelude::*;
34
use pyo3::types::{PyDict, PyTuple};
45

5-
use crate::build_tools::safe_repr;
6-
76
#[pyclass(module = "pydantic_core._pydantic_core", get_all, frozen, freelist = 100)]
87
#[derive(Debug, Clone)]
98
pub struct ArgsKwargs {

src/build_tools.rs

Lines changed: 11 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,15 @@
1-
use std::borrow::Cow;
21
use std::error::Error;
32
use std::fmt;
43

5-
use pyo3::exceptions::{PyException, PyKeyError};
4+
use pyo3::exceptions::PyException;
65
use pyo3::prelude::*;
76
use pyo3::types::{PyDict, PyList, PyString};
87
use pyo3::{intern, FromPyObject, PyErrArguments};
98

109
use crate::errors::{ErrorMode, ValError};
10+
use crate::tools::SchemaDict;
1111
use crate::ValidationError;
1212

13-
pub trait SchemaDict<'py> {
14-
fn get_as<T>(&'py self, key: &PyString) -> PyResult<Option<T>>
15-
where
16-
T: FromPyObject<'py>;
17-
18-
fn get_as_req<T>(&'py self, key: &PyString) -> PyResult<T>
19-
where
20-
T: FromPyObject<'py>;
21-
}
22-
23-
impl<'py> SchemaDict<'py> for PyDict {
24-
fn get_as<T>(&'py self, key: &PyString) -> PyResult<Option<T>>
25-
where
26-
T: FromPyObject<'py>,
27-
{
28-
match self.get_item(key) {
29-
Some(t) => Ok(Some(<T>::extract(t)?)),
30-
None => Ok(None),
31-
}
32-
}
33-
34-
fn get_as_req<T>(&'py self, key: &PyString) -> PyResult<T>
35-
where
36-
T: FromPyObject<'py>,
37-
{
38-
match self.get_item(key) {
39-
Some(t) => <T>::extract(t),
40-
None => py_err!(PyKeyError; "{}", key),
41-
}
42-
}
43-
}
44-
45-
impl<'py> SchemaDict<'py> for Option<&PyDict> {
46-
fn get_as<T>(&'py self, key: &PyString) -> PyResult<Option<T>>
47-
where
48-
T: FromPyObject<'py>,
49-
{
50-
match self {
51-
Some(d) => d.get_as(key),
52-
None => Ok(None),
53-
}
54-
}
55-
56-
#[cfg_attr(has_no_coverage, no_coverage)]
57-
fn get_as_req<T>(&'py self, key: &PyString) -> PyResult<T>
58-
where
59-
T: FromPyObject<'py>,
60-
{
61-
match self {
62-
Some(d) => d.get_as_req(key),
63-
None => py_err!(PyKeyError; "{}", key),
64-
}
65-
}
66-
}
67-
6813
pub fn schema_or_config<'py, T>(
6914
schema: &'py PyDict,
7015
config: Option<&'py PyDict>,
@@ -196,58 +141,25 @@ impl SchemaError {
196141
}
197142
}
198143

199-
macro_rules! py_error_type {
144+
macro_rules! py_schema_error_type {
200145
($msg:expr) => {
201-
crate::build_tools::py_error_type!(crate::build_tools::SchemaError; $msg)
146+
crate::tools::py_error_type!(crate::build_tools::SchemaError; $msg)
202147
};
203148
($msg:expr, $( $msg_args:expr ),+ ) => {
204-
crate::build_tools::py_error_type!(crate::build_tools::SchemaError; $msg, $( $msg_args ),+)
205-
};
206-
207-
($error_type:ty; $msg:expr) => {
208-
<$error_type>::new_err($msg)
209-
};
210-
211-
($error_type:ty; $msg:expr, $( $msg_args:expr ),+ ) => {
212-
<$error_type>::new_err(format!($msg, $( $msg_args ),+))
149+
crate::tools::py_error_type!(crate::build_tools::SchemaError; $msg, $( $msg_args ),+)
213150
};
214151
}
215-
pub(crate) use py_error_type;
152+
pub(crate) use py_schema_error_type;
216153

217-
macro_rules! py_err {
154+
macro_rules! py_schema_err {
218155
($msg:expr) => {
219-
Err(crate::build_tools::py_error_type!($msg))
156+
Err(crate::build_tools::py_schema_error_type!($msg))
220157
};
221158
($msg:expr, $( $msg_args:expr ),+ ) => {
222-
Err(crate::build_tools::py_error_type!($msg, $( $msg_args ),+))
223-
};
224-
225-
($error_type:ty; $msg:expr) => {
226-
Err(crate::build_tools::py_error_type!($error_type; $msg))
159+
Err(crate::build_tools::py_schema_error_type!($msg, $( $msg_args ),+))
227160
};
228-
229-
($error_type:ty; $msg:expr, $( $msg_args:expr ),+ ) => {
230-
Err(crate::build_tools::py_error_type!($error_type; $msg, $( $msg_args ),+))
231-
};
232-
}
233-
pub(crate) use py_err;
234-
235-
pub fn function_name(f: &PyAny) -> PyResult<String> {
236-
match f.getattr(intern!(f.py(), "__name__")) {
237-
Ok(name) => name.extract(),
238-
_ => f.repr()?.extract(),
239-
}
240-
}
241-
242-
pub fn safe_repr(v: &PyAny) -> Cow<str> {
243-
if let Ok(s) = v.repr() {
244-
s.to_string_lossy()
245-
} else if let Ok(name) = v.get_type().name() {
246-
format!("<unprintable {name} object>").into()
247-
} else {
248-
"<unprintable object>".into()
249-
}
250161
}
162+
pub(crate) use py_schema_err;
251163

252164
#[derive(Debug, Clone)]
253165
pub(crate) enum ExtraBehavior {
@@ -274,7 +186,7 @@ impl ExtraBehavior {
274186
Some("allow") => Self::Allow,
275187
Some("ignore") => Self::Ignore,
276188
Some("forbid") => Self::Forbid,
277-
Some(v) => return py_err!("Invalid extra_behavior: `{}`", v),
189+
Some(v) => return py_schema_err!("Invalid extra_behavior: `{}`", v),
278190
None => default,
279191
};
280192
Ok(res)

src/definitions.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use pyo3::prelude::*;
99

1010
use ahash::AHashMap;
1111

12-
use crate::build_tools::py_err;
12+
use crate::build_tools::py_schema_err;
1313

1414
// An integer id for the reference
1515
pub type ReferenceId = usize;
@@ -68,7 +68,7 @@ impl<T: Clone + std::fmt::Debug> DefinitionsBuilder<T> {
6868
let next_id = self.definitions.len();
6969
match self.definitions.entry(reference.clone()) {
7070
Entry::Occupied(mut entry) => match entry.get_mut().value.replace(value) {
71-
Some(_) => py_err!("Duplicate ref: `{}`", reference),
71+
Some(_) => py_schema_err!("Duplicate ref: `{}`", reference),
7272
None => Ok(entry.get().id),
7373
},
7474
Entry::Vacant(entry) => {
@@ -86,11 +86,11 @@ impl<T: Clone + std::fmt::Debug> DefinitionsBuilder<T> {
8686
pub fn get_definition(&self, reference_id: ReferenceId) -> PyResult<&T> {
8787
let (reference, def) = match self.definitions.iter().find(|(_, def)| def.id == reference_id) {
8888
Some(v) => v,
89-
None => return py_err!("Definitions error: no definition for ReferenceId `{}`", reference_id),
89+
None => return py_schema_err!("Definitions error: no definition for ReferenceId `{}`", reference_id),
9090
};
9191
match def.value.as_ref() {
9292
Some(v) => Ok(v),
93-
None => py_err!(
93+
None => py_schema_err!(
9494
"Definitions error: attempted to use `{}` before it was filled",
9595
reference
9696
),
@@ -103,7 +103,7 @@ impl<T: Clone + std::fmt::Debug> DefinitionsBuilder<T> {
103103
let mut defs: Vec<(usize, T)> = Vec::new();
104104
for (reference, def) in self.definitions.into_iter() {
105105
match def.value {
106-
None => return py_err!("Definitions error: definition {} was never filled", reference),
106+
None => return py_schema_err!("Definitions error: definition {} was never filled", reference),
107107
Some(v) => defs.push((def.id, v)),
108108
}
109109
}

src/errors/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use pyo3::once_cell::GILOnceCell;
77
use pyo3::prelude::*;
88
use pyo3::types::{PyDict, PyList};
99

10-
use crate::build_tools::{py_err, py_error_type};
10+
use crate::tools::{py_err, py_error_type};
1111
use strum::{Display, EnumMessage, IntoEnumIterator};
1212
use strum_macros::EnumIter;
1313

src/errors/validation_exception.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ use serde::{Serialize, Serializer};
1313

1414
use serde_json::ser::PrettyFormatter;
1515

16-
use crate::build_tools::{py_error_type, safe_repr, SchemaDict};
16+
use crate::build_tools::py_schema_error_type;
1717
use crate::errors::LocItem;
1818
use crate::get_version;
1919
use crate::serializers::{SerMode, SerializationState};
20+
use crate::tools::{safe_repr, SchemaDict};
2021

2122
use super::line_error::ValLineError;
2223
use super::location::Location;
@@ -83,7 +84,7 @@ impl ValidationError {
8384
}
8485

8586
pub fn omit_error() -> PyErr {
86-
py_error_type!("Uncaught Omit error, please check your usage of `default` validators.")
87+
py_schema_error_type!("Uncaught Omit error, please check your usage of `default` validators.")
8788
}
8889
}
8990

src/input/input_python.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use pyo3::types::{
1010
use pyo3::types::{PyDictItems, PyDictKeys, PyDictValues};
1111
use pyo3::{ffi, intern, AsPyPointer, PyTypeInfo};
1212

13-
use crate::build_tools::safe_repr;
1413
use crate::errors::{ErrorType, InputValue, LocItem, ValError, ValResult};
14+
use crate::tools::safe_repr;
1515
use crate::{ArgsKwargs, PyMultiHostUrl, PyUrl};
1616

1717
use super::datetime::{

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ mod lazy_index_map;
1818
mod lookup_key;
1919
mod recursion_guard;
2020
mod serializers;
21+
mod tools;
2122
mod url;
2223
mod validators;
2324

src/lookup_key.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ use pyo3::exceptions::{PyAttributeError, PyTypeError};
55
use pyo3::prelude::*;
66
use pyo3::types::{PyDict, PyList, PyMapping, PyString};
77

8-
use crate::build_tools::py_err;
8+
use crate::build_tools::py_schema_err;
99
use crate::errors::{ErrorType, ValLineError};
1010
use crate::input::{Input, JsonInput, JsonObject};
11+
use crate::tools::py_err;
1112

1213
/// Used got getting items from python dicts, python objects, or JSON objects, in different ways
1314
#[derive(Debug, Clone)]
@@ -73,7 +74,7 @@ impl LookupKey {
7374
let list: &PyList = value.downcast()?;
7475
let first = match list.get_item(0) {
7576
Ok(v) => v,
76-
Err(_) => return py_err!("Lookup paths should have at least one element"),
77+
Err(_) => return py_schema_err!("Lookup paths should have at least one element"),
7778
};
7879
let mut locs: Vec<LookupPath> = if first.downcast::<PyString>().is_ok() {
7980
// list of strings rather than list of lists
@@ -331,7 +332,7 @@ impl LookupPath {
331332
.collect::<PyResult<Vec<PathItem>>>()?;
332333

333334
if v.is_empty() {
334-
py_err!("Each alias path should have at least one element")
335+
py_schema_err!("Each alias path should have at least one element")
335336
} else {
336337
Ok(Self(v))
337338
}

src/serializers/computed_fields.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use pyo3::types::{PyDict, PyList, PyString};
44
use serde::ser::SerializeMap;
55
use serde::Serialize;
66

7-
use crate::build_tools::{py_error_type, SchemaDict};
7+
use crate::build_tools::py_schema_error_type;
88
use crate::definitions::DefinitionsBuilder;
99
use crate::serializers::filter::SchemaFilter;
1010
use crate::serializers::shared::{BuildSerializer, CombinedSerializer, PydanticSerializer, TypeSerializer};
11+
use crate::tools::SchemaDict;
1112

1213
use super::errors::py_err_se_err;
1314
use super::Extra;
@@ -105,7 +106,7 @@ impl ComputedField {
105106
let property_name: &PyString = schema.get_as_req(intern!(py, "property_name"))?;
106107
let return_schema = schema.get_as_req(intern!(py, "return_schema"))?;
107108
let serializer = CombinedSerializer::build(return_schema, config, definitions)
108-
.map_err(|e| py_error_type!("Computed field `{}`:\n {}", property_name, e))?;
109+
.map_err(|e| py_schema_error_type!("Computed field `{}`:\n {}", property_name, e))?;
109110
let alias_py: &PyString = schema.get_as(intern!(py, "alias"))?.unwrap_or(property_name);
110111
Ok(Self {
111112
property_name: property_name.extract()?,

src/serializers/config.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ use pyo3::{intern, PyNativeType};
77

88
use serde::ser::Error;
99

10-
use crate::build_tools::{py_err, SchemaDict};
10+
use crate::build_tools::py_schema_err;
1111
use crate::input::pytimedelta_as_duration;
12+
use crate::tools::SchemaDict;
1213

1314
use super::errors::py_err_se_err;
1415

@@ -57,7 +58,7 @@ impl TimedeltaMode {
5758
match s {
5859
Some("iso8601") => Ok(Self::Iso8601),
5960
Some("float") => Ok(Self::Float),
60-
Some(s) => py_err!(
61+
Some(s) => py_schema_err!(
6162
"Invalid timedelta serialization mode: `{}`, expected `iso8601` or `float`",
6263
s
6364
),
@@ -133,7 +134,7 @@ impl BytesMode {
133134
let base64_config = match s {
134135
Some("utf8") => None,
135136
Some("base64") => Some(base64::Config::new(base64::CharacterSet::UrlSafe, true)),
136-
Some(s) => return py_err!("Invalid bytes serialization mode: `{}`, expected `utf8` or `base64`", s),
137+
Some(s) => return py_schema_err!("Invalid bytes serialization mode: `{}`, expected `utf8` or `base64`", s),
137138
None => None,
138139
};
139140
Ok(Self { base64_config })

src/serializers/filter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use pyo3::intern;
77
use pyo3::prelude::*;
88
use pyo3::types::{PyBool, PyDict, PySet};
99

10-
use crate::build_tools::SchemaDict;
10+
use crate::tools::SchemaDict;
1111

1212
#[derive(Debug, Clone, Default)]
1313
pub(crate) struct SchemaFilter<T> {

src/serializers/infer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ use pyo3::types::{
1010

1111
use serde::ser::{Error, Serialize, SerializeMap, SerializeSeq, Serializer};
1212

13-
use crate::build_tools::{py_err, safe_repr};
1413
use crate::serializers::errors::SERIALIZATION_ERR_MARKER;
1514
use crate::serializers::filter::SchemaFilter;
1615
use crate::serializers::shared::{PydanticSerializer, TypeSerializer};
1716
use crate::serializers::SchemaSerializer;
17+
use crate::tools::{py_err, safe_repr};
1818
use crate::url::{PyMultiHostUrl, PyUrl};
1919

2020
use super::errors::{py_err_se_err, PydanticSerializationError};

0 commit comments

Comments
 (0)