Skip to content

Commit 33f4ad9

Browse files
committed
remove most uses of into_ref
1 parent 38982e8 commit 33f4ad9

File tree

16 files changed

+329
-187
lines changed

16 files changed

+329
-187
lines changed

benches/main.rs

Lines changed: 216 additions & 74 deletions
Large diffs are not rendered by default.

src/build_tools.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl SchemaError {
9090
ValidationError::new(line_errors, "Schema".to_object(py), InputType::Python, false);
9191
let schema_error = SchemaError(SchemaErrorEnum::ValidationError(validation_error));
9292
match Py::new(py, schema_error) {
93-
Ok(err) => PyErr::from_value(err.into_ref(py)),
93+
Ok(err) => PyErr::from_value(err.as_ref(py)),
9494
Err(err) => err,
9595
}
9696
}

src/input/datetime.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ fn time_as_tzinfo<'py>(py: Python<'py>, time: &Time) -> PyResult<Option<Py2<'py,
228228
match time.tz_offset {
229229
Some(offset) => {
230230
let tz_info: TzInfo = offset.try_into()?;
231-
Ok(Some(Py::new(py, tz_info)?.into_ref(py).extract()?))
231+
Ok(Some(Py2::new(py, tz_info)?.into_any().downcast_into()?))
232232
}
233233
None => Ok(None),
234234
}

src/input/input_abstract.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,16 @@ pub trait Input<'a>: fmt::Debug + ToPyObject + AsLocItem + Sized {
119119

120120
fn validate_float(&'a self, strict: bool) -> ValResult<ValidationMatch<EitherFloat<'a>>>;
121121

122-
fn validate_decimal(&'a self, strict: bool, py: Python<'a>) -> ValResult<&'a PyAny> {
122+
fn validate_decimal(&'a self, strict: bool, py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
123123
if strict {
124124
self.strict_decimal(py)
125125
} else {
126126
self.lax_decimal(py)
127127
}
128128
}
129-
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny>;
129+
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<Py2<'a, PyAny>>;
130130
#[cfg_attr(has_coverage_attribute, coverage(off))]
131-
fn lax_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
131+
fn lax_decimal(&'a self, py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
132132
self.strict_decimal(py)
133133
}
134134

src/input/input_json.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,12 @@ impl<'a> Input<'a> for JsonValue {
154154
}
155155
}
156156

157-
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
157+
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
158158
match self {
159-
JsonValue::Float(f) => create_decimal(PyString::new(py, &f.to_string()), self, py),
159+
JsonValue::Float(f) => create_decimal(&PyString::new2(py, &f.to_string()), self),
160160

161161
JsonValue::Str(..) | JsonValue::Int(..) | JsonValue::BigInt(..) => {
162-
create_decimal(self.to_object(py).into_ref(py), self, py)
162+
create_decimal(self.to_object(py).attach(py), self)
163163
}
164164
_ => Err(ValError::new(ErrorTypeDefaults::DecimalType, self)),
165165
}
@@ -392,8 +392,8 @@ impl<'a> Input<'a> for String {
392392
str_as_float(self, self).map(ValidationMatch::lax)
393393
}
394394

395-
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
396-
create_decimal(self.to_object(py).into_ref(py), self, py)
395+
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
396+
create_decimal(self.to_object(py).attach(py), self)
397397
}
398398

399399
#[cfg_attr(has_coverage_attribute, coverage(off))]

src/input/input_python.rs

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,26 @@ impl<'a> Input<'a> for Py2<'a, PyAny> {
142142

143143
fn validate_args(&'a self) -> ValResult<GenericArguments<'a>> {
144144
if let Ok(dict) = self.downcast::<PyDict>() {
145-
Ok(PyArgs::new(None, Some(dict.clone().into_gil_ref())).into())
145+
Ok(PyArgs::new(None, Some(dict.clone())).into())
146146
} else if let Ok(args_kwargs) = self.extract::<ArgsKwargs>() {
147-
let args = args_kwargs.args.into_ref(self.py());
148-
let kwargs = args_kwargs.kwargs.map(|d| d.into_ref(self.py()));
147+
let args = args_kwargs.args.attach_into(self.py());
148+
let kwargs = args_kwargs.kwargs.map(|d| d.attach_into(self.py()));
149149
Ok(PyArgs::new(Some(args), kwargs).into())
150150
} else if let Ok(tuple) = self.downcast::<PyTuple>() {
151-
Ok(PyArgs::new(Some(tuple.clone().into_gil_ref()), None).into())
151+
Ok(PyArgs::new(Some(tuple.clone()), None).into())
152152
} else if let Ok(list) = self.downcast::<PyList>() {
153-
Ok(PyArgs::new(Some(list.to_tuple().into_gil_ref()), None).into())
153+
Ok(PyArgs::new(Some(list.to_tuple()), None).into())
154154
} else {
155155
Err(ValError::new(ErrorTypeDefaults::ArgumentsType, self))
156156
}
157157
}
158158

159159
fn validate_dataclass_args(&'a self, class_name: &str) -> ValResult<GenericArguments<'a>> {
160160
if let Ok(dict) = self.downcast::<PyDict>() {
161-
Ok(PyArgs::new(None, Some(dict.clone().into_gil_ref())).into())
161+
Ok(PyArgs::new(None, Some(dict.clone())).into())
162162
} else if let Ok(args_kwargs) = self.extract::<ArgsKwargs>() {
163-
let args = args_kwargs.args.into_ref(self.py());
164-
let kwargs = args_kwargs.kwargs.map(|d| d.into_ref(self.py()));
163+
let args = args_kwargs.args.attach_into(self.py());
164+
let kwargs = args_kwargs.kwargs.map(|d| d.attach_into(self.py()));
165165
Ok(PyArgs::new(Some(args), kwargs).into())
166166
} else {
167167
let class_name = class_name.to_string();
@@ -206,12 +206,12 @@ impl<'a> Input<'a> for Py2<'a, PyAny> {
206206
}
207207
} else if coerce_numbers_to_str && !PyBool::is_exact_type_of(self.as_gil_ref()) && {
208208
let py = self.py();
209-
let decimal_type: Py<PyType> = get_decimal_type(py);
209+
let decimal_type = get_decimal_type(py);
210210

211211
// only allow int, float, and decimal (not bool)
212212
self.is_instance_of::<PyInt>()
213213
|| self.is_instance_of::<PyFloat>()
214-
|| self.is_instance(decimal_type.attach(py)).unwrap_or_default()
214+
|| self.is_instance(decimal_type).unwrap_or_default()
215215
} {
216216
Ok(self.str()?.into_gil_ref().into())
217217
} else if let Some(enum_val) = maybe_as_enum(self.as_gil_ref()) {
@@ -314,7 +314,7 @@ impl<'a> Input<'a> for Py2<'a, PyAny> {
314314
} else if self.is_exact_instance_of::<PyFloat>() {
315315
float_as_int(self, self.extract::<f64>()?)
316316
} else if let Ok(decimal) = self.strict_decimal(self.py()) {
317-
decimal_as_int(self.py(), self, decimal)
317+
decimal_as_int(self, &decimal)
318318
} else if let Ok(float) = self.extract::<f64>() {
319319
float_as_int(self, float)
320320
} else if let Some(enum_val) = maybe_as_enum(self.as_gil_ref()) {
@@ -356,17 +356,16 @@ impl<'a> Input<'a> for Py2<'a, PyAny> {
356356
Err(ValError::new(ErrorTypeDefaults::FloatType, self))
357357
}
358358

359-
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
360-
let decimal_type_obj: Py<PyType> = get_decimal_type(py);
361-
let decimal_type = decimal_type_obj.as_ref(py);
359+
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
360+
let decimal_type = get_decimal_type(py);
362361
// Fast path for existing decimal objects
363-
if self.as_gil_ref().is_exact_instance(decimal_type) {
364-
return Ok(self.as_gil_ref());
362+
if self.is_exact_instance(decimal_type) {
363+
return Ok(self.clone());
365364
}
366365

367366
// Try subclasses of decimals, they will be upcast to Decimal
368-
if self.as_gil_ref().is_instance(decimal_type)? {
369-
return create_decimal(self.as_gil_ref(), self, py);
367+
if self.is_instance(decimal_type)? {
368+
return create_decimal(self, self);
370369
}
371370

372371
Err(ValError::new(
@@ -378,22 +377,21 @@ impl<'a> Input<'a> for Py2<'a, PyAny> {
378377
))
379378
}
380379

381-
fn lax_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
382-
let decimal_type_obj: Py<PyType> = get_decimal_type(py);
383-
let decimal_type = decimal_type_obj.as_ref(py);
380+
fn lax_decimal(&'a self, py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
381+
let decimal_type = get_decimal_type(py);
384382
// Fast path for existing decimal objects
385-
if self.as_gil_ref().is_exact_instance(decimal_type) {
386-
return Ok(self.as_gil_ref());
383+
if self.is_exact_instance(decimal_type) {
384+
return Ok(self.clone());
387385
}
388386

389387
if self.is_instance_of::<PyString>() || (self.is_instance_of::<PyInt>() && !self.is_instance_of::<PyBool>()) {
390388
// checking isinstance for str / int / bool is fast compared to decimal / float
391-
create_decimal(self.as_gil_ref(), self, py)
392-
} else if self.as_gil_ref().is_instance(decimal_type)? {
389+
create_decimal(self, self)
390+
} else if self.is_instance(decimal_type)? {
393391
// upcast subclasses to decimal
394-
return create_decimal(self.as_gil_ref(), self, py);
392+
return create_decimal(self, self);
395393
} else if self.is_instance_of::<PyFloat>() {
396-
create_decimal(self.str()?.into_gil_ref(), self, py)
394+
create_decimal(self.str()?.as_any(), self)
397395
} else {
398396
Err(ValError::new(ErrorTypeDefaults::DecimalType, self))
399397
}

src/input/input_string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ impl<'a> Input<'a> for StringMapping<'a> {
129129
}
130130
}
131131

132-
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
132+
fn strict_decimal(&'a self, _py: Python<'a>) -> ValResult<Py2<'a, PyAny>> {
133133
match self {
134-
Self::String(s) => create_decimal(s.as_gil_ref(), self, py),
134+
Self::String(s) => create_decimal(s, self),
135135
Self::Mapping(_) => Err(ValError::new(ErrorTypeDefaults::DecimalType, self)),
136136
}
137137
}

src/input/return_enums.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -722,12 +722,9 @@ pub struct PyArgs<'py> {
722722
pub kwargs: Option<Py2<'py, PyDict>>,
723723
}
724724

725-
impl<'a> PyArgs<'a> {
726-
pub fn new(args: Option<&'a PyTuple>, kwargs: Option<&'a PyDict>) -> Self {
727-
Self {
728-
args: args.map(|args| Py2::borrowed_from_gil_ref(&args).clone()),
729-
kwargs: kwargs.map(|kwargs| Py2::borrowed_from_gil_ref(&kwargs).clone()),
730-
}
725+
impl<'py> PyArgs<'py> {
726+
pub fn new(args: Option<Py2<'py, PyTuple>>, kwargs: Option<Py2<'py, PyDict>>) -> Self {
727+
Self { args, kwargs }
731728
}
732729
}
733730

src/input/shared.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use pyo3::prelude::Py2;
1+
use pyo3::prelude::*;
22
use pyo3::sync::GILOnceCell;
33
use pyo3::{intern, Py, PyAny, Python, ToPyObject};
44

@@ -142,15 +142,17 @@ pub fn float_as_int<'a>(input: &'a impl Input<'a>, float: f64) -> ValResult<Eith
142142
}
143143
}
144144

145-
pub fn decimal_as_int<'a>(py: Python, input: &'a impl Input<'a>, decimal: &'a PyAny) -> ValResult<EitherInt<'a>> {
145+
pub fn decimal_as_int<'a>(input: &'a impl Input<'a>, decimal: &Py2<'a, PyAny>) -> ValResult<EitherInt<'a>> {
146+
let py = decimal.py();
146147
if !decimal.call_method0(intern!(py, "is_finite"))?.extract::<bool>()? {
147148
return Err(ValError::new(ErrorTypeDefaults::FiniteNumber, input));
148149
}
149150
let (numerator, denominator) = decimal
150151
.call_method0(intern!(py, "as_integer_ratio"))?
151-
.extract::<(&PyAny, &PyAny)>()?;
152+
.into_gil_ref()
153+
.extract::<(Py2<'_, PyAny>, Py2<'_, PyAny>)>()?;
152154
if denominator.extract::<i64>().map_or(true, |d| d != 1) {
153155
return Err(ValError::new(ErrorTypeDefaults::IntFromFloat, input));
154156
}
155-
Ok(EitherInt::Py(Py2::borrowed_from_gil_ref(&numerator).clone()))
157+
Ok(EitherInt::Py(numerator))
156158
}

src/serializers/infer.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,7 @@ pub(crate) fn infer_json_key_known<'py>(ob_type: ObType, key: &'py PyAny, extra:
653653
ObType::Unknown => {
654654
if let Some(fallback) = extra.fallback {
655655
let next_key = fallback.call1((key,))?;
656-
// totally unnecessary step to placate rust's lifetime rules
657-
let next_key = next_key.to_object(key.py()).into_ref(key.py());
658-
infer_json_key(next_key, extra)
656+
infer_json_key(next_key, extra).map(|cow| Cow::Owned(cow.into_owned()))
659657
} else if extra.serialize_unknown {
660658
Ok(serialize_unknown(key))
661659
} else {

src/serializers/type_serializers/format.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ impl TypeSerializer for FormatSerializer {
123123

124124
fn json_key<'py>(&self, key: &'py PyAny, _extra: &Extra) -> PyResult<Cow<'py, str>> {
125125
if self.when_used.should_use_json(key) {
126-
let v = self.call(key).map_err(PydanticSerializationError::new_err)?;
127-
let py_str: &PyString = v.into_ref(key.py()).downcast()?;
128-
Ok(Cow::Borrowed(py_str.to_str()?))
126+
let py_str = self
127+
.call(key)
128+
.map_err(PydanticSerializationError::new_err)?
129+
.attach_into(key.py())
130+
.downcast_into::<PyString>()?;
131+
Ok(Cow::Owned(py_str.to_str()?.to_owned()))
129132
} else {
130133
none_json_key()
131134
}

src/serializers/type_serializers/function.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,10 @@ macro_rules! function_type_serializer {
211211
let py = value.py();
212212
match self.call(value, include, exclude, extra) {
213213
// None for include/exclude here, as filtering should be done
214-
Ok((true, v)) => self
215-
.return_serializer
216-
.to_python(v.into_ref(py), None, None, extra),
214+
Ok((true, v)) => self.return_serializer.to_python(v.as_ref(py), None, None, extra),
217215
Ok((false, v)) => self
218216
.get_fallback_serializer()
219-
.to_python(v.into_ref(py), None, None, extra),
217+
.to_python(v.as_ref(py), None, None, extra),
220218
Err(err) => {
221219
on_error(py, err, &self.function_name, extra)?;
222220
infer_to_python(value, include, exclude, extra)
@@ -227,8 +225,14 @@ macro_rules! function_type_serializer {
227225
fn json_key<'py>(&self, key: &'py PyAny, extra: &Extra) -> PyResult<Cow<'py, str>> {
228226
let py = key.py();
229227
match self.call(key, None, None, extra) {
230-
Ok((true, v)) => self.return_serializer.json_key(v.into_ref(py), extra),
231-
Ok((false, v)) => self.get_fallback_serializer().json_key(v.into_ref(py), extra),
228+
Ok((true, v)) => self
229+
.return_serializer
230+
.json_key(v.as_ref(py), extra)
231+
.map(|cow| Cow::Owned(cow.into_owned())),
232+
Ok((false, v)) => self
233+
.get_fallback_serializer()
234+
.json_key(v.as_ref(py), extra)
235+
.map(|cow| Cow::Owned(cow.into_owned())),
232236
Err(err) => {
233237
on_error(py, err, &self.function_name, extra)?;
234238
infer_json_key(key, extra)
@@ -249,11 +253,11 @@ macro_rules! function_type_serializer {
249253
// None for include/exclude here, as filtering should be done
250254
Ok((true, v)) => {
251255
self.return_serializer
252-
.serde_serialize(v.into_ref(py), serializer, None, None, extra)
256+
.serde_serialize(v.as_ref(py), serializer, None, None, extra)
253257
}
254258
Ok((false, v)) => {
255259
self.get_fallback_serializer()
256-
.serde_serialize(v.into_ref(py), serializer, None, None, extra)
260+
.serde_serialize(v.as_ref(py), serializer, None, None, extra)
257261
}
258262
Err(err) => {
259263
on_error(py, err, &self.function_name, extra).map_err(py_err_se_err)?;

src/serializers/type_serializers/model.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,18 @@ impl ModelSerializer {
125125
}
126126
}
127127

128-
fn get_inner_value<'py>(&self, model: &'py PyAny, extra: &Extra) -> PyResult<&'py PyAny> {
128+
fn get_inner_value<'py>(&self, model: &Py2<'py, PyAny>, extra: &Extra) -> PyResult<Py2<'py, PyAny>> {
129129
let py = model.py();
130-
let mut attrs: &PyDict = model.getattr(intern!(py, "__dict__"))?.downcast()?;
130+
let mut attrs = model.getattr(intern!(py, "__dict__"))?.downcast_into::<PyDict>()?;
131131

132132
if extra.exclude_unset {
133-
let fields_set: &PySet = model.getattr(intern!(py, "__pydantic_fields_set__"))?.downcast()?;
133+
let fields_set = model
134+
.getattr(intern!(py, "__pydantic_fields_set__"))?
135+
.downcast_into::<PySet>()?;
134136

135137
let new_attrs = attrs.copy()?;
136138
for key in new_attrs.keys() {
137-
if !fields_set.contains(key)? {
139+
if !fields_set.contains(&key)? {
138140
new_attrs.del_item(key)?;
139141
}
140142
}
@@ -143,10 +145,10 @@ impl ModelSerializer {
143145

144146
if self.has_extra {
145147
let model_extra = model.getattr(intern!(py, "__pydantic_extra__"))?;
146-
let py_tuple = (attrs, model_extra).to_object(py);
147-
Ok(py_tuple.into_ref(py))
148+
let py_tuple = (attrs, model_extra).to_object(py).attach_into(py);
149+
Ok(py_tuple)
148150
} else {
149-
Ok(attrs)
151+
Ok(attrs.into_any())
150152
}
151153
}
152154
}
@@ -178,8 +180,9 @@ impl TypeSerializer for ModelSerializer {
178180
})?;
179181
self.serializer.to_python(root, include, exclude, &extra)
180182
} else if self.allow_value(value, &extra)? {
181-
let inner_value = self.get_inner_value(value, &extra)?;
182-
self.serializer.to_python(inner_value, include, exclude, &extra)
183+
let inner_value = self.get_inner_value(Py2::borrowed_from_gil_ref(&value), &extra)?;
184+
self.serializer
185+
.to_python(inner_value.as_gil_ref(), include, exclude, &extra)
183186
} else {
184187
extra.warnings.on_fallback_py(self.get_name(), value, &extra)?;
185188
infer_to_python(value, include, exclude, &extra)
@@ -215,9 +218,11 @@ impl TypeSerializer for ModelSerializer {
215218
self.serializer
216219
.serde_serialize(root, serializer, include, exclude, &extra)
217220
} else if self.allow_value(value, &extra).map_err(py_err_se_err)? {
218-
let inner_value = self.get_inner_value(value, &extra).map_err(py_err_se_err)?;
221+
let inner_value = self
222+
.get_inner_value(Py2::borrowed_from_gil_ref(&value), &extra)
223+
.map_err(py_err_se_err)?;
219224
self.serializer
220-
.serde_serialize(inner_value, serializer, include, exclude, &extra)
225+
.serde_serialize(inner_value.as_gil_ref(), serializer, include, exclude, &extra)
221226
} else {
222227
extra.warnings.on_fallback_ser::<S>(self.get_name(), value, &extra)?;
223228
infer_serialize(value, serializer, include, exclude, &extra)

0 commit comments

Comments
 (0)