Skip to content

Commit a24b08e

Browse files
committed
deactivate gil-refs
1 parent c972150 commit a24b08e

Some content is hidden

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

101 files changed

+2454
-2214
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ include = [
2727
rust-version = "1.70"
2828

2929
[dependencies]
30-
pyo3 = { version = "0.21.0-beta.0", features = ["generate-import-lib", "num-bigint", "gil-refs"] }
30+
pyo3 = { version = "0.21.0-beta.0", features = ["generate-import-lib", "num-bigint"] }
3131
regex = "1.10.3"
3232
strum = { version = "0.25.0", features = ["derive"] }
3333
strum_macros = "0.26.1"

benches/main.rs

Lines changed: 106 additions & 98 deletions
Large diffs are not rendered by default.

src/argument_markers.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ pub struct ArgsKwargs {
1515

1616
impl ArgsKwargs {
1717
fn eq(&self, py: Python, other: &Self) -> PyResult<bool> {
18-
if self.args.as_ref(py).eq(other.args.as_ref(py))? {
18+
if self.args.bind(py).eq(other.args.bind(py))? {
1919
match (&self.kwargs, &other.kwargs) {
20-
(Some(d1), Some(d2)) => d1.as_ref(py).eq(d2.as_ref(py)),
20+
(Some(d1), Some(d2)) => d1.bind(py).eq(d2.bind(py)),
2121
(None, None) => Ok(true),
2222
_ => Ok(false),
2323
}
@@ -55,9 +55,9 @@ impl ArgsKwargs {
5555
}
5656

5757
pub fn __repr__(&self, py: Python) -> String {
58-
let args = safe_repr(self.args.as_ref(py));
58+
let args = safe_repr(self.args.bind(py));
5959
match self.kwargs {
60-
Some(ref d) => format!("ArgsKwargs({args}, {})", safe_repr(d.as_ref(py))),
60+
Some(ref d) => format!("ArgsKwargs({args}, {})", safe_repr(d.bind(py))),
6161
None => format!("ArgsKwargs({args})"),
6262
}
6363
}

src/build_tools.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use crate::tools::SchemaDict;
1212
use crate::ValidationError;
1313

1414
pub fn schema_or_config<'py, T>(
15-
schema: &'py PyDict,
16-
config: Option<&'py PyDict>,
15+
schema: &Bound<'py, PyDict>,
16+
config: Option<&Bound<'py, PyDict>>,
1717
schema_key: &Bound<'py, PyString>,
1818
config_key: &Bound<'py, PyString>,
1919
) -> PyResult<Option<T>>
@@ -30,8 +30,8 @@ where
3030
}
3131

3232
pub fn schema_or_config_same<'py, T>(
33-
schema: &'py PyDict,
34-
config: Option<&'py PyDict>,
33+
schema: &Bound<'py, PyDict>,
34+
config: Option<&Bound<'py, PyDict>>,
3535
key: &Bound<'py, PyString>,
3636
) -> PyResult<Option<T>>
3737
where
@@ -40,7 +40,7 @@ where
4040
schema_or_config(schema, config, key, key)
4141
}
4242

43-
pub fn is_strict(schema: &PyDict, config: Option<&PyDict>) -> PyResult<bool> {
43+
pub fn is_strict(schema: &Bound<'_, PyDict>, config: Option<&Bound<'_, PyDict>>) -> PyResult<bool> {
4444
let py = schema.py();
4545
Ok(schema_or_config_same(schema, config, intern!(py, "strict"))?.unwrap_or(false))
4646
}
@@ -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_bound(err.into_bound(py).into_any()),
9494
Err(err) => err,
9595
}
9696
}
@@ -124,7 +124,7 @@ impl SchemaError {
124124

125125
fn errors(&self, py: Python) -> PyResult<Py<PyList>> {
126126
match &self.0 {
127-
SchemaErrorEnum::Message(_) => Ok(PyList::empty(py).into_py(py)),
127+
SchemaErrorEnum::Message(_) => Ok(PyList::empty_bound(py).unbind()),
128128
SchemaErrorEnum::ValidationError(error) => error.errors(py, false, false, true),
129129
}
130130
}
@@ -174,18 +174,18 @@ pub(crate) enum ExtraBehavior {
174174
impl ExtraBehavior {
175175
pub fn from_schema_or_config(
176176
py: Python,
177-
schema: &PyDict,
178-
config: Option<&PyDict>,
177+
schema: &Bound<'_, PyDict>,
178+
config: Option<&Bound<'_, PyDict>>,
179179
default: Self,
180180
) -> PyResult<Self> {
181-
let extra_behavior = schema_or_config::<Option<&str>>(
181+
let extra_behavior = schema_or_config::<Option<Bound<'_, PyString>>>(
182182
schema,
183183
config,
184184
intern!(py, "extra_behavior"),
185185
intern!(py, "extra_fields_behavior"),
186186
)?
187187
.flatten();
188-
let res = match extra_behavior {
188+
let res = match extra_behavior.as_ref().map(|s| s.to_str()).transpose()? {
189189
Some("allow") => Self::Allow,
190190
Some("ignore") => Self::Ignore,
191191
Some("forbid") => Self::Forbid,

src/errors/line_error.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use pyo3::exceptions::PyTypeError;
22
use pyo3::prelude::*;
3-
use pyo3::PyDowncastError;
3+
use pyo3::DowncastError;
4+
use pyo3::DowncastIntoError;
45

56
use jiter::JsonValue;
67

@@ -35,8 +36,14 @@ impl From<PyErr> for ValError {
3536
}
3637
}
3738

38-
impl From<PyDowncastError<'_>> for ValError {
39-
fn from(py_downcast: PyDowncastError) -> Self {
39+
impl From<DowncastError<'_, '_>> for ValError {
40+
fn from(py_downcast: DowncastError) -> Self {
41+
Self::InternalErr(PyTypeError::new_err(py_downcast.to_string()))
42+
}
43+
}
44+
45+
impl From<DowncastIntoError<'_>> for ValError {
46+
fn from(py_downcast: DowncastIntoError) -> Self {
4047
Self::InternalErr(PyTypeError::new_err(py_downcast.to_string()))
4148
}
4249
}

src/errors/location.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,9 @@ static EMPTY_TUPLE: GILOnceCell<PyObject> = GILOnceCell::new();
126126
impl ToPyObject for Location {
127127
fn to_object(&self, py: Python<'_>) -> PyObject {
128128
match self {
129-
Self::List(loc) => PyTuple::new(py, loc.iter().rev()).to_object(py),
129+
Self::List(loc) => PyTuple::new_bound(py, loc.iter().rev()).to_object(py),
130130
Self::Empty => EMPTY_TUPLE
131-
.get_or_init(py, || PyTuple::empty(py).to_object(py))
131+
.get_or_init(py, || PyTuple::empty_bound(py).to_object(py))
132132
.clone_ref(py),
133133
}
134134
}
@@ -193,12 +193,12 @@ impl Serialize for Location {
193193
}
194194
}
195195

196-
impl TryFrom<Option<&PyAny>> for Location {
196+
impl TryFrom<Option<&Bound<'_, PyAny>>> for Location {
197197
type Error = PyErr;
198198

199199
/// Only ever called by ValidationError -> PyLineError to convert user input to our internal Location
200200
/// Thus this expects the location to *not* be reversed and reverses it before storing it.
201-
fn try_from(location: Option<&PyAny>) -> PyResult<Self> {
201+
fn try_from(location: Option<&Bound<'_, PyAny>>) -> PyResult<Self> {
202202
if let Some(location) = location {
203203
let mut loc_vec: Vec<LocItem> = if let Ok(tuple) = location.downcast::<PyTuple>() {
204204
tuple.iter().map(Into::into).collect()

src/errors/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub use self::validation_exception::ValidationError;
1313
pub use self::value_exception::{PydanticCustomError, PydanticKnownError, PydanticOmit, PydanticUseDefault};
1414

1515
pub fn py_err_string(py: Python, err: PyErr) -> String {
16-
let value = err.value(py);
16+
let value = err.value_bound(py);
1717
match value.get_type().qualname() {
1818
Ok(type_name) => match value.str() {
1919
Ok(py_str) => {

src/errors/types.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ use crate::tools::{extract_i64, py_err, py_error_type};
1818
use super::PydanticCustomError;
1919

2020
#[pyfunction]
21-
pub fn list_all_errors(py: Python) -> PyResult<&PyList> {
22-
let mut errors: Vec<&PyDict> = Vec::with_capacity(100);
21+
pub fn list_all_errors(py: Python) -> PyResult<Bound<'_, PyList>> {
22+
let mut errors: Vec<Bound<'_, PyDict>> = Vec::with_capacity(100);
2323
for error_type in ErrorType::iter() {
2424
if !matches!(error_type, ErrorType::CustomError { .. }) {
25-
let d = PyDict::new(py);
25+
let d = PyDict::new_bound(py);
2626
d.set_item("type", error_type.to_string())?;
2727
let message_template_python = error_type.message_template_python();
2828
d.set_item("message_template_python", message_template_python)?;
@@ -39,7 +39,7 @@ pub fn list_all_errors(py: Python) -> PyResult<&PyList> {
3939
errors.push(d);
4040
}
4141
}
42-
Ok(PyList::new(py, errors))
42+
Ok(PyList::new_bound(py, errors))
4343
}
4444

4545
fn field_from_context<'py, T: FromPyObject<'py>>(
@@ -121,15 +121,16 @@ macro_rules! error_types {
121121
}
122122
}
123123

124-
fn py_dict_update_ctx(&self, py: Python, dict: &PyDict) -> PyResult<bool> {
124+
fn py_dict_update_ctx(&self, py: Python, dict: &Bound<'_, PyDict>) -> PyResult<bool> {
125+
use pyo3::types::PyMapping;
125126
match self {
126127
$(
127128
Self::$item { context, $($key,)* } => {
128129
$(
129130
dict.set_item::<&str, Py<PyAny>>(stringify!($key), $key.to_object(py))?;
130131
)*
131132
if let Some(ctx) = context {
132-
dict.update(ctx.as_ref(py).downcast()?)?;
133+
dict.update(ctx.bind(py).downcast::<PyMapping>()?)?;
133134
Ok(true)
134135
} else {
135136
Ok(false)
@@ -669,20 +670,20 @@ impl ErrorType {
669670
Self::ValueError { error, .. } => {
670671
let error = &error
671672
.as_ref()
672-
.map_or(Cow::Borrowed("None"), |v| Cow::Owned(v.as_ref(py).to_string()));
673+
.map_or(Cow::Borrowed("None"), |v| Cow::Owned(v.bind(py).to_string()));
673674
render!(tmpl, error)
674675
}
675676
Self::AssertionError { error, .. } => {
676677
let error = &error
677678
.as_ref()
678-
.map_or(Cow::Borrowed("None"), |v| Cow::Owned(v.as_ref(py).to_string()));
679+
.map_or(Cow::Borrowed("None"), |v| Cow::Owned(v.bind(py).to_string()));
679680
render!(tmpl, error)
680681
}
681682
Self::CustomError {
682683
message_template,
683684
context,
684685
..
685-
} => PydanticCustomError::format_message(message_template, context.as_ref().map(|c| c.as_ref(py))),
686+
} => PydanticCustomError::format_message(message_template, context.as_ref().map(|c| c.bind(py))),
686687
Self::LiteralError { expected, .. } => render!(tmpl, expected),
687688
Self::DateParsing { error, .. } => render!(tmpl, error),
688689
Self::DateFromDatetimeParsing { error, .. } => render!(tmpl, error),
@@ -729,8 +730,8 @@ impl ErrorType {
729730
}
730731

731732
pub fn py_dict(&self, py: Python) -> PyResult<Option<Py<PyDict>>> {
732-
let dict = PyDict::new(py);
733-
let custom_ctx_used = self.py_dict_update_ctx(py, dict)?;
733+
let dict = PyDict::new_bound(py);
734+
let custom_ctx_used = self.py_dict_update_ctx(py, &dict)?;
734735

735736
if let Self::CustomError { .. } = self {
736737
if custom_ctx_used {
@@ -785,7 +786,7 @@ impl From<Int> for Number {
785786
}
786787

787788
impl FromPyObject<'_> for Number {
788-
fn extract(obj: &PyAny) -> PyResult<Self> {
789+
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
789790
if let Some(int) = extract_i64(obj) {
790791
Ok(Number::Int(int))
791792
} else if let Ok(float) = obj.extract::<f64>() {

src/errors/validation_exception.rs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl ValidationError {
7373
return cause_problem;
7474
}
7575
}
76-
PyErr::from_value(err.as_ref(py))
76+
PyErr::from_value_bound(err.into_bound(py).into_any())
7777
}
7878
Err(err) => err,
7979
}
@@ -202,9 +202,9 @@ fn include_url_env(py: Python) -> bool {
202202
match std::env::var_os("PYDANTIC_ERRORS_OMIT_URL") {
203203
Some(val) => {
204204
// We don't care whether warning succeeded or not, hence the assignment
205-
let _ = PyErr::warn(
205+
let _ = PyErr::warn_bound(
206206
py,
207-
py.get_type::<pyo3::exceptions::PyDeprecationWarning>(),
207+
&py.get_type_bound::<pyo3::exceptions::PyDeprecationWarning>(),
208208
"PYDANTIC_ERRORS_OMIT_URL is deprecated, use PYDANTIC_ERRORS_INCLUDE_URL instead",
209209
1,
210210
);
@@ -253,14 +253,17 @@ impl ValidationError {
253253
fn from_exception_data(
254254
py: Python,
255255
title: PyObject,
256-
line_errors: &PyList,
256+
line_errors: Bound<'_, PyList>,
257257
input_type: &str,
258258
hide_input: bool,
259259
) -> PyResult<Py<Self>> {
260260
Py::new(
261261
py,
262262
Self {
263-
line_errors: line_errors.iter().map(PyLineError::try_from).collect::<PyResult<_>>()?,
263+
line_errors: line_errors
264+
.iter()
265+
.map(|error| PyLineError::try_from(&error))
266+
.collect::<PyResult<_>>()?,
264267
title,
265268
input_type: InputType::try_from(input_type)?,
266269
hide_input,
@@ -287,7 +290,7 @@ impl ValidationError {
287290
) -> PyResult<Py<PyList>> {
288291
let url_prefix = get_url_prefix(py, include_url);
289292
let mut iteration_error = None;
290-
let list = PyList::new(
293+
let list = PyList::new_bound(
291294
py,
292295
// PyList::new takes ExactSizeIterator, so if an error occurs during iteration we
293296
// fill the list with None before returning the error; the list will then be thrown
@@ -318,7 +321,7 @@ impl ValidationError {
318321
include_url: bool,
319322
include_context: bool,
320323
include_input: bool,
321-
) -> PyResult<&'py PyString> {
324+
) -> PyResult<Bound<'py, PyString>> {
322325
let state = SerializationState::new("iso8601", "utf8", "constants")?;
323326
let extra = state.extra(py, &SerMode::Json, true, false, false, true, None, None);
324327
let serializer = ValidationErrorSerializer {
@@ -347,7 +350,7 @@ impl ValidationError {
347350
}
348351
};
349352
let s = from_utf8(&bytes).map_err(json_py_err)?;
350-
Ok(PyString::new(py, s))
353+
Ok(PyString::new_bound(py, s))
351354
}
352355

353356
fn __repr__(&self, py: Python) -> String {
@@ -358,12 +361,12 @@ impl ValidationError {
358361
self.__repr__(py)
359362
}
360363

361-
fn __reduce__(slf: &PyCell<Self>) -> PyResult<(&PyAny, PyObject)> {
364+
fn __reduce__<'py>(slf: &Bound<'py, Self>) -> PyResult<(Bound<'py, PyAny>, PyObject)> {
362365
let py = slf.py();
363366
let callable = slf.getattr("from_exception_data")?;
364367
let borrow = slf.try_borrow()?;
365368
let args = (
366-
borrow.title.as_ref(py),
369+
borrow.title.bind(py),
367370
borrow.errors(py, include_url_env(py), true, true)?,
368371
borrow.input_type.into_py(py),
369372
borrow.hide_input,
@@ -463,11 +466,11 @@ impl From<PyLineError> for ValLineError {
463466
}
464467
}
465468

466-
impl TryFrom<&PyAny> for PyLineError {
469+
impl TryFrom<&Bound<'_, PyAny>> for PyLineError {
467470
type Error = PyErr;
468471

469-
fn try_from(value: &PyAny) -> PyResult<Self> {
470-
let dict: &PyDict = value.downcast()?;
472+
fn try_from(value: &Bound<'_, PyAny>) -> PyResult<Self> {
473+
let dict = value.downcast::<PyDict>()?;
471474
let py = value.py();
472475

473476
let type_raw = dict
@@ -485,7 +488,7 @@ impl TryFrom<&PyAny> for PyLineError {
485488
));
486489
};
487490

488-
let location = Location::try_from(dict.get_item("loc")?)?;
491+
let location = Location::try_from(dict.get_item("loc")?.as_ref())?;
489492

490493
let input_value = match dict.get_item("input")? {
491494
Some(i) => i.into_py(py),
@@ -513,7 +516,7 @@ impl PyLineError {
513516
input_type: InputType,
514517
include_input: bool,
515518
) -> PyResult<PyObject> {
516-
let dict = PyDict::new(py);
519+
let dict = PyDict::new_bound(py);
517520
dict.set_item("type", self.error_type.type_string())?;
518521
dict.set_item("loc", self.location.to_object(py))?;
519522
dict.set_item("msg", self.error_type.render_message(py, input_type)?)?;
@@ -555,9 +558,9 @@ impl PyLineError {
555558
write!(output, " {message} [type={}", self.error_type.type_string())?;
556559

557560
if !hide_input {
558-
let input_value = self.input_value.as_ref(py);
561+
let input_value = self.input_value.bind(py);
559562
let input_str = safe_repr(input_value);
560-
truncate_input_value!(output, &input_str);
563+
truncate_input_value!(output, &input_str.to_cow());
561564

562565
if let Ok(type_) = input_value.get_type().qualname() {
563566
write!(output, ", input_type={type_}")?;
@@ -663,13 +666,13 @@ impl<'py> Serialize for PyLineErrorSerializer<'py> {
663666
if self.include_input {
664667
map.serialize_entry(
665668
"input",
666-
&self.extra.serialize_infer(self.line_error.input_value.as_ref(py)),
669+
&self.extra.serialize_infer(self.line_error.input_value.bind(py)),
667670
)?;
668671
}
669672

670673
if self.include_context {
671674
if let Some(context) = self.line_error.error_type.py_dict(py).map_err(py_err_json::<S>)? {
672-
map.serialize_entry("ctx", &self.extra.serialize_infer(context.as_ref(py)))?;
675+
map.serialize_entry("ctx", &self.extra.serialize_infer(context.bind(py)))?;
673676
}
674677
}
675678
if let Some(url_prefix) = self.url_prefix {

0 commit comments

Comments
 (0)