Skip to content

Commit f409e00

Browse files
replace ultra_strict with new union implementation (#867)
Co-authored-by: Samuel Colvin <[email protected]>
1 parent d08b4f3 commit f409e00

Some content is hidden

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

51 files changed

+1011
-1339
lines changed

src/definitions.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,9 @@ use crate::{build_tools::py_schema_err, py_gc::PyGcTraverse};
3131
#[derive(Clone)]
3232
pub struct Definitions<T>(AHashMap<Arc<String>, Definition<T>>);
3333

34-
impl<T> Definitions<T> {
35-
pub fn values(&self) -> impl Iterator<Item = &Definition<T>> {
36-
self.0.values()
37-
}
38-
}
39-
4034
/// Internal type which contains a definition to be filled
4135
pub struct Definition<T>(Arc<DefinitionInner<T>>);
4236

43-
impl<T> Definition<T> {
44-
pub fn get(&self) -> Option<&T> {
45-
self.0.value.get()
46-
}
47-
}
48-
4937
struct DefinitionInner<T> {
5038
value: OnceLock<T>,
5139
name: LazyName,

src/input/input_abstract.rs

Lines changed: 26 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use pyo3::{intern, prelude::*};
66

77
use jiter::JsonValue;
88

9-
use crate::errors::{AsLocItem, InputValue, ValResult};
9+
use crate::errors::{AsLocItem, ErrorTypeDefaults, InputValue, ValError, ValResult};
1010
use crate::tools::py_err;
1111
use crate::{PyMultiHostUrl, PyUrl};
1212

1313
use super::datetime::{EitherDate, EitherDateTime, EitherTime, EitherTimedelta};
1414
use super::return_enums::{EitherBytes, EitherInt, EitherString};
15-
use super::{EitherFloat, GenericArguments, GenericIterable, GenericIterator, GenericMapping};
15+
use super::{EitherFloat, GenericArguments, GenericIterable, GenericIterator, GenericMapping, ValidationMatch};
1616

1717
#[derive(Debug, Clone, Copy)]
1818
pub enum InputType {
@@ -48,7 +48,7 @@ impl TryFrom<&str> for InputType {
4848
/// the convention is to either implement:
4949
/// * `strict_*` & `lax_*` if they have different behavior
5050
/// * or, `validate_*` and `strict_*` to just call `validate_*` if the behavior for strict and lax is the same
51-
pub trait Input<'a>: fmt::Debug + ToPyObject + AsLocItem {
51+
pub trait Input<'a>: fmt::Debug + ToPyObject + AsLocItem + Sized {
5252
fn as_error_value(&'a self) -> InputValue<'a>;
5353

5454
fn identity(&self) -> Option<usize> {
@@ -91,85 +91,37 @@ pub trait Input<'a>: fmt::Debug + ToPyObject + AsLocItem {
9191

9292
fn parse_json(&'a self) -> ValResult<'a, JsonValue>;
9393

94-
fn validate_str(&'a self, strict: bool, coerce_numbers_to_str: bool) -> ValResult<EitherString<'a>> {
95-
if strict {
96-
self.strict_str()
97-
} else {
98-
self.lax_str(coerce_numbers_to_str)
99-
}
100-
}
101-
fn strict_str(&'a self) -> ValResult<EitherString<'a>>;
102-
#[cfg_attr(has_coverage_attribute, coverage(off))]
103-
fn lax_str(&'a self, _coerce_numbers_to_str: bool) -> ValResult<EitherString<'a>> {
104-
self.strict_str()
105-
}
94+
fn validate_str(
95+
&'a self,
96+
strict: bool,
97+
coerce_numbers_to_str: bool,
98+
) -> ValResult<ValidationMatch<EitherString<'a>>>;
10699

107-
fn validate_bytes(&'a self, strict: bool) -> ValResult<EitherBytes<'a>> {
108-
if strict {
109-
self.strict_bytes()
110-
} else {
111-
self.lax_bytes()
112-
}
113-
}
114-
fn strict_bytes(&'a self) -> ValResult<EitherBytes<'a>>;
115-
#[cfg_attr(has_coverage_attribute, coverage(off))]
116-
fn lax_bytes(&'a self) -> ValResult<EitherBytes<'a>> {
117-
self.strict_bytes()
118-
}
100+
fn validate_bytes(&'a self, strict: bool) -> ValResult<ValidationMatch<EitherBytes<'a>>>;
119101

120-
fn validate_bool(&self, strict: bool) -> ValResult<bool> {
121-
if strict {
122-
self.strict_bool()
123-
} else {
124-
self.lax_bool()
125-
}
126-
}
127-
fn strict_bool(&self) -> ValResult<bool>;
128-
#[cfg_attr(has_coverage_attribute, coverage(off))]
129-
fn lax_bool(&self) -> ValResult<bool> {
130-
self.strict_bool()
131-
}
102+
fn validate_bool(&self, strict: bool) -> ValResult<'_, ValidationMatch<bool>>;
132103

133-
fn validate_int(&'a self, strict: bool) -> ValResult<EitherInt<'a>> {
134-
if strict {
135-
self.strict_int()
136-
} else {
137-
self.lax_int()
138-
}
139-
}
140-
fn strict_int(&'a self) -> ValResult<EitherInt<'a>>;
141-
#[cfg_attr(has_coverage_attribute, coverage(off))]
142-
fn lax_int(&'a self) -> ValResult<EitherInt<'a>> {
143-
self.strict_int()
144-
}
104+
fn validate_int(&'a self, strict: bool) -> ValResult<'a, ValidationMatch<EitherInt<'a>>>;
145105

146-
/// Extract an EitherInt from the input, only allowing exact
147-
/// matches for an Int (no subclasses)
148106
fn exact_int(&'a self) -> ValResult<EitherInt<'a>> {
149-
self.strict_int()
107+
self.validate_int(true).and_then(|val_match| {
108+
val_match
109+
.require_exact()
110+
.ok_or_else(|| ValError::new(ErrorTypeDefaults::IntType, self))
111+
})
150112
}
151113

152114
/// Extract a String from the input, only allowing exact
153115
/// matches for a String (no subclasses)
154116
fn exact_str(&'a self) -> ValResult<EitherString<'a>> {
155-
self.strict_str()
117+
self.validate_str(true, false).and_then(|val_match| {
118+
val_match
119+
.require_exact()
120+
.ok_or_else(|| ValError::new(ErrorTypeDefaults::StringType, self))
121+
})
156122
}
157123

158-
fn validate_float(&'a self, strict: bool, ultra_strict: bool) -> ValResult<EitherFloat<'a>> {
159-
if ultra_strict {
160-
self.ultra_strict_float()
161-
} else if strict {
162-
self.strict_float()
163-
} else {
164-
self.lax_float()
165-
}
166-
}
167-
fn ultra_strict_float(&'a self) -> ValResult<EitherFloat<'a>>;
168-
fn strict_float(&'a self) -> ValResult<EitherFloat<'a>>;
169-
#[cfg_attr(has_coverage_attribute, coverage(off))]
170-
fn lax_float(&'a self) -> ValResult<EitherFloat<'a>> {
171-
self.strict_float()
172-
}
124+
fn validate_float(&'a self, strict: bool) -> ValResult<'a, ValidationMatch<EitherFloat<'a>>>;
173125

174126
fn validate_decimal(&'a self, strict: bool, py: Python<'a>) -> ValResult<&'a PyAny> {
175127
if strict {
@@ -257,87 +209,25 @@ pub trait Input<'a>: fmt::Debug + ToPyObject + AsLocItem {
257209

258210
fn validate_iter(&self) -> ValResult<GenericIterator>;
259211

260-
fn validate_date(&self, strict: bool) -> ValResult<EitherDate> {
261-
if strict {
262-
self.strict_date()
263-
} else {
264-
self.lax_date()
265-
}
266-
}
267-
fn strict_date(&self) -> ValResult<EitherDate>;
268-
#[cfg_attr(has_coverage_attribute, coverage(off))]
269-
fn lax_date(&self) -> ValResult<EitherDate> {
270-
self.strict_date()
271-
}
212+
fn validate_date(&self, strict: bool) -> ValResult<ValidationMatch<EitherDate>>;
272213

273214
fn validate_time(
274215
&self,
275216
strict: bool,
276217
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
277-
) -> ValResult<EitherTime> {
278-
if strict {
279-
self.strict_time(microseconds_overflow_behavior)
280-
} else {
281-
self.lax_time(microseconds_overflow_behavior)
282-
}
283-
}
284-
fn strict_time(
285-
&self,
286-
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
287-
) -> ValResult<EitherTime>;
288-
#[cfg_attr(has_coverage_attribute, coverage(off))]
289-
fn lax_time(
290-
&self,
291-
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
292-
) -> ValResult<EitherTime> {
293-
self.strict_time(microseconds_overflow_behavior)
294-
}
218+
) -> ValResult<ValidationMatch<EitherTime>>;
295219

296220
fn validate_datetime(
297221
&self,
298222
strict: bool,
299223
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
300-
) -> ValResult<EitherDateTime> {
301-
if strict {
302-
self.strict_datetime(microseconds_overflow_behavior)
303-
} else {
304-
self.lax_datetime(microseconds_overflow_behavior)
305-
}
306-
}
307-
fn strict_datetime(
308-
&self,
309-
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
310-
) -> ValResult<EitherDateTime>;
311-
#[cfg_attr(has_coverage_attribute, coverage(off))]
312-
fn lax_datetime(
313-
&self,
314-
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
315-
) -> ValResult<EitherDateTime> {
316-
self.strict_datetime(microseconds_overflow_behavior)
317-
}
224+
) -> ValResult<ValidationMatch<EitherDateTime>>;
318225

319226
fn validate_timedelta(
320227
&self,
321228
strict: bool,
322229
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
323-
) -> ValResult<EitherTimedelta> {
324-
if strict {
325-
self.strict_timedelta(microseconds_overflow_behavior)
326-
} else {
327-
self.lax_timedelta(microseconds_overflow_behavior)
328-
}
329-
}
330-
fn strict_timedelta(
331-
&self,
332-
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
333-
) -> ValResult<EitherTimedelta>;
334-
#[cfg_attr(has_coverage_attribute, coverage(off))]
335-
fn lax_timedelta(
336-
&self,
337-
microseconds_overflow_behavior: speedate::MicrosecondsPrecisionOverflowBehavior,
338-
) -> ValResult<EitherTimedelta> {
339-
self.strict_timedelta(microseconds_overflow_behavior)
340-
}
230+
) -> ValResult<ValidationMatch<EitherTimedelta>>;
341231
}
342232

343233
/// The problem to solve here is that iterating a `StringMapping` returns an owned

0 commit comments

Comments
 (0)