Skip to content

Commit 7a996db

Browse files
committed
chore: add negative tests, refactor total seconds to encapsulate more common logic
1 parent 21be1a2 commit 7a996db

File tree

2 files changed

+36
-15
lines changed

2 files changed

+36
-15
lines changed

src/serializers/config.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ serialization_mode! {
109109
}
110110

111111
impl TimedeltaMode {
112-
fn total_seconds<'py>(py_timedelta: &Bound<'py, PyDelta>) -> PyResult<Bound<'py, PyAny>> {
112+
fn total_seconds<'py>(py: Python, either_delta: &EitherTimedelta) -> PyResult<Bound<'py, PyAny>> {
113+
let py_timedelta = either_delta.try_into_py(py)?;
113114
py_timedelta.call_method0(intern!(py_timedelta.py(), "total_seconds"))
114115
}
115116

@@ -122,15 +123,13 @@ impl TimedeltaMode {
122123
Self::Float => {
123124
// convert to int via a py timedelta not duration since we know this this case the input would have
124125
// been a py timedelta
125-
let py_timedelta = either_delta.try_into_py(py)?;
126-
let seconds = Self::total_seconds(&py_timedelta)?;
126+
let seconds = Self::total_seconds(py, either_delta)?;
127127
Ok(seconds.into_py(py))
128128
}
129129
Self::Millisecond => {
130130
// convert to int via a py timedelta not duration since we know this this case the input would have
131131
// been a py timedelta
132-
let py_timedelta = either_delta.try_into_py(py)?;
133-
let seconds: f64 = Self::total_seconds(&py_timedelta)?.extract()?;
132+
let seconds = Self::total_seconds(py, either_delta)?;
134133
let object: Bound<PyFloat> = PyFloat::new_bound(py, seconds * 1000.0);
135134
Ok(object.into_py(py))
136135
}
@@ -144,13 +143,11 @@ impl TimedeltaMode {
144143
Ok(d.to_string().into())
145144
}
146145
Self::Float => {
147-
let py_timedelta = either_delta.try_into_py(py)?;
148-
let seconds: f64 = Self::total_seconds(&py_timedelta)?.extract()?;
146+
let seconds = Self::total_seconds(py, either_delta)?.extract()?;
149147
Ok(seconds.to_string().into())
150148
}
151149
Self::Millisecond => {
152-
let py_timedelta = either_delta.try_into_py(py)?;
153-
let seconds: f64 = Self::total_seconds(&py_timedelta)?.extract()?;
150+
let seconds = Self::total_seconds(py, either_delta)?.extract()?;
154151
let milliseconds: f64 = seconds * 1000.0;
155152
Ok(milliseconds.to_string().into())
156153
}
@@ -169,15 +166,15 @@ impl TimedeltaMode {
169166
serializer.serialize_str(&d.to_string())
170167
}
171168
Self::Float => {
172-
let py_timedelta = either_delta.try_into_py(py).map_err(py_err_se_err)?;
173-
let seconds = Self::total_seconds(&py_timedelta).map_err(py_err_se_err)?;
174-
let seconds: f64 = seconds.extract().map_err(py_err_se_err)?;
169+
let seconds = Self::total_seconds(py, either_delta)?
170+
.extract()?
171+
.map_err(py_err_se_err)?;
175172
serializer.serialize_f64(seconds)
176173
}
177174
Self::Millisecond => {
178-
let py_timedelta = either_delta.try_into_py(py).map_err(py_err_se_err)?;
179-
let seconds = Self::total_seconds(&py_timedelta).map_err(py_err_se_err)?;
180-
let seconds: f64 = seconds.extract().map_err(py_err_se_err)?;
175+
let seconds = Self::total_seconds(py, either_delta)?
176+
.extract()?
177+
.map_err(py_err_se_err)?;
181178
let milliseconds: f64 = seconds * 1000.0;
182179
serializer.serialize_f64(milliseconds)
183180
}

tests/serializers/test_any.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ def test_any_config_timedelta_float_faction():
201201
assert s.to_json({one_half_s: 'foo'}) == b'{"1.5":"foo"}'
202202

203203

204+
def test_any_config_timedelta_float_negative():
205+
s = SchemaSerializer(core_schema.any_schema(), config={'ser_json_timedelta': 'float'})
206+
one_half_s = timedelta(seconds=-1.5)
207+
assert s.to_python(one_half_s) == one_half_s
208+
assert s.to_python(one_half_s, mode='json') == -1.5
209+
assert s.to_json(one_half_s) == b'-1.5'
210+
211+
assert s.to_python({one_half_s: 'foo'}) == {one_half_s: 'foo'}
212+
assert s.to_python({one_half_s: 'foo'}, mode='json') == {'-1.5': 'foo'}
213+
assert s.to_json({one_half_s: 'foo'}) == b'{"-1.5":"foo"}'
214+
215+
204216
def test_any_config_timedelta_millisecond():
205217
s = SchemaSerializer(core_schema.any_schema(), config={'ser_json_timedelta': 'millisecond'})
206218
h2 = timedelta(hours=2)
@@ -225,6 +237,18 @@ def test_any_config_timedelta_millisecond_fraction():
225237
assert s.to_json({h2: 'foo'}) == b'{"1500":"foo"}'
226238

227239

240+
def test_any_config_timedelta_millisecond_negative():
241+
s = SchemaSerializer(core_schema.any_schema(), config={'ser_json_timedelta': 'millisecond'})
242+
h2 = timedelta(seconds=-1.5)
243+
assert s.to_python(h2) == h2
244+
assert s.to_python(h2, mode='json') == -1500.0
245+
assert s.to_json(h2) == b'-1500.0'
246+
247+
assert s.to_python({h2: 'foo'}) == {h2: 'foo'}
248+
assert s.to_python({h2: 'foo'}, mode='json') == {'-1500': 'foo'}
249+
assert s.to_json({h2: 'foo'}) == b'{"-1500":"foo"}'
250+
251+
228252
def test_recursion(any_serializer):
229253
v = [1, 2]
230254
v.append(v)

0 commit comments

Comments
 (0)