Skip to content

Commit 10095b5

Browse files
authored
tidy up some remaining PyO3 GIL Refs (#1225)
1 parent 71d54a2 commit 10095b5

File tree

12 files changed

+62
-59
lines changed

12 files changed

+62
-59
lines changed

benches/main.rs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use pyo3::types::{PyDict, PyString};
99

1010
use _pydantic_core::{validate_core_schema, SchemaValidator};
1111

12-
fn build_schema_validator_with_globals(py: Python, code: &str, globals: Option<&PyDict>) -> SchemaValidator {
13-
let mut schema = py.eval(code, globals, None).unwrap().extract().unwrap();
12+
fn build_schema_validator_with_globals(py: Python, code: &str, globals: Option<&Bound<'_, PyDict>>) -> SchemaValidator {
13+
let mut schema = py.eval_bound(code, globals, None).unwrap().extract().unwrap();
1414
schema = validate_core_schema(&schema, None).unwrap().extract().unwrap();
1515
SchemaValidator::py_new(py, &schema, None).unwrap()
1616
}
@@ -71,7 +71,7 @@ fn list_int_input(py: Python<'_>) -> (SchemaValidator, PyObject) {
7171
(0..100).map(|x| x.to_string()).collect::<Vec<String>>().join(",")
7272
);
7373

74-
let input = py.eval(&code, None, None).unwrap();
74+
let input = py.eval_bound(&code, None, None).unwrap();
7575
(validator, input.to_object(py))
7676
}
7777

@@ -117,7 +117,7 @@ fn list_error_json(bench: &mut Bencher) {
117117
match validator.validate_json(py, &json(py, &code), None, None, None) {
118118
Ok(_) => panic!("unexpectedly valid"),
119119
Err(e) => {
120-
let v = e.value(py);
120+
let v = e.value_bound(py);
121121
// println!("error: {}", v.to_string());
122122
assert_eq!(v.getattr("title").unwrap().to_string(), "list[int]");
123123
let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap();
@@ -144,12 +144,12 @@ fn list_error_python_input(py: Python<'_>) -> (SchemaValidator, PyObject) {
144144
.join(", ")
145145
);
146146

147-
let input = py.eval(&code, None, None).unwrap().extract().unwrap();
147+
let input = py.eval_bound(&code, None, None).unwrap().extract().unwrap();
148148

149149
match validator.validate_python(py, &input, None, None, None, None) {
150150
Ok(_) => panic!("unexpectedly valid"),
151151
Err(e) => {
152-
let v = e.value(py);
152+
let v = e.value_bound(py);
153153
// println!("error: {}", v.to_string());
154154
assert_eq!(v.getattr("title").unwrap().to_string(), "list[int]");
155155
let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap();
@@ -211,7 +211,7 @@ fn list_any_python(bench: &mut Bencher) {
211211
"[{}]",
212212
(0..100).map(|x| x.to_string()).collect::<Vec<String>>().join(",")
213213
);
214-
let input = py.eval(&code, None, None).unwrap().to_object(py);
214+
let input = py.eval_bound(&code, None, None).unwrap().to_object(py);
215215
let input = black_box(input.bind(py));
216216
bench.iter(|| {
217217
let v = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -263,7 +263,7 @@ fn dict_python(bench: &mut Bencher) {
263263
.collect::<Vec<String>>()
264264
.join(", ")
265265
);
266-
let input = py.eval(&code, None, None).unwrap().to_object(py);
266+
let input = py.eval_bound(&code, None, None).unwrap().to_object(py);
267267
let input = black_box(input.bind(py));
268268
bench.iter(|| {
269269
let v = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -292,12 +292,12 @@ fn dict_value_error(bench: &mut Bencher) {
292292
.join(", ")
293293
);
294294

295-
let input = py.eval(&code, None, None).unwrap().to_object(py).into_bound(py);
295+
let input = py.eval_bound(&code, None, None).unwrap().to_object(py).into_bound(py);
296296

297297
match validator.validate_python(py, &input, None, None, None, None) {
298298
Ok(_) => panic!("unexpectedly valid"),
299299
Err(e) => {
300-
let v = e.value(py);
300+
let v = e.value_bound(py);
301301
// println!("error: {}", v.to_string());
302302
assert_eq!(v.getattr("title").unwrap().to_string(), "dict[str,constrained-int]");
303303
let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap();
@@ -370,7 +370,7 @@ fn typed_dict_python(bench: &mut Bencher) {
370370
);
371371

372372
let code = r#"{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 0}"#.to_string();
373-
let input = py.eval(&code, None, None).unwrap().to_object(py);
373+
let input = py.eval_bound(&code, None, None).unwrap().to_object(py);
374374
let input = black_box(input.bind(py));
375375
bench.iter(|| {
376376
let v = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -410,13 +410,13 @@ fn typed_dict_deep_error(bench: &mut Bencher) {
410410

411411
let code = "{'field_a': '1', 'field_b': {'field_c': '2', 'field_d': {'field_e': '4', 'field_f': 'xx'}}}";
412412

413-
let input = py.eval(code, None, None).unwrap().to_object(py);
413+
let input = py.eval_bound(code, None, None).unwrap().to_object(py);
414414
let input = black_box(input.bind(py));
415415

416416
match validator.validate_python(py, &input, None, None, None, None) {
417417
Ok(_) => panic!("unexpectedly valid"),
418418
Err(e) => {
419-
let v = e.value(py);
419+
let v = e.value_bound(py);
420420
// println!("error: {}", v.to_string());
421421
assert_eq!(v.getattr("title").unwrap().to_string(), "typed-dict");
422422
let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap();
@@ -438,7 +438,7 @@ fn typed_dict_deep_error(bench: &mut Bencher) {
438438
#[bench]
439439
fn complete_model(bench: &mut Bencher) {
440440
Python::with_gil(|py| {
441-
let sys_path = py.import("sys").unwrap().getattr("path").unwrap();
441+
let sys_path = py.import_bound("sys").unwrap().getattr("path").unwrap();
442442
sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap();
443443

444444
let complete_schema = py.import_bound("complete_schema").unwrap();
@@ -458,7 +458,7 @@ fn complete_model(bench: &mut Bencher) {
458458
#[bench]
459459
fn nested_model_using_definitions(bench: &mut Bencher) {
460460
Python::with_gil(|py| {
461-
let sys_path = py.import("sys").unwrap().getattr("path").unwrap();
461+
let sys_path = py.import_bound("sys").unwrap().getattr("path").unwrap();
462462
sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap();
463463

464464
let complete_schema = py.import_bound("nested_schema").unwrap();
@@ -480,7 +480,7 @@ fn nested_model_using_definitions(bench: &mut Bencher) {
480480
#[bench]
481481
fn nested_model_inlined(bench: &mut Bencher) {
482482
Python::with_gil(|py| {
483-
let sys_path = py.import("sys").unwrap().getattr("path").unwrap();
483+
let sys_path = py.import_bound("sys").unwrap().getattr("path").unwrap();
484484
sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap();
485485

486486
let complete_schema = py.import_bound("nested_schema").unwrap();
@@ -520,7 +520,7 @@ fn literal_strings_few_small_python(bench: &mut Bencher) {
520520
Python::with_gil(|py| {
521521
let validator = build_schema_validator(py, "{'type': 'literal', 'expected': [f'{idx}' for idx in range(5)]}");
522522

523-
let input = py.eval("'4'", None, None).unwrap();
523+
let input = py.eval_bound("'4'", None, None).unwrap();
524524
let input = input.to_object(py).into_bound(py);
525525
let input_str: String = input.extract().unwrap();
526526
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -540,7 +540,7 @@ fn literal_strings_few_large_python(bench: &mut Bencher) {
540540
"{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(5)]}",
541541
);
542542

543-
let input = py.eval("'a' * 25 + '4'", None, None).unwrap();
543+
let input = py.eval_bound("'a' * 25 + '4'", None, None).unwrap();
544544
let input = input.to_object(py).into_bound(py);
545545
let input_str: String = input.extract().unwrap();
546546
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -556,7 +556,7 @@ fn literal_strings_few_large_python(bench: &mut Bencher) {
556556
fn literal_enums_few_python(bench: &mut Bencher) {
557557
Python::with_gil(|py| {
558558
let globals = PyDict::new_bound(py);
559-
py.run(
559+
py.run_bound(
560560
r#"
561561
from enum import Enum
562562
@@ -566,18 +566,18 @@ class Foo(Enum):
566566
v3 = object()
567567
v4 = object()
568568
"#,
569-
Some(globals.as_gil_ref()),
569+
Some(&globals),
570570
None,
571571
)
572572
.unwrap();
573573

574574
let validator = build_schema_validator_with_globals(
575575
py,
576576
"{'type': 'literal', 'expected': [Foo.v1, Foo.v2, Foo.v3, Foo.v4]}",
577-
Some(globals.as_gil_ref()),
577+
Some(&globals),
578578
);
579579

580-
let input = py.eval("Foo.v4", Some(globals.as_gil_ref()), None).unwrap();
580+
let input = py.eval_bound("Foo.v4", Some(&globals), None).unwrap();
581581
let input = input.to_object(py).into_bound(py);
582582
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
583583
assert!(input.eq(result).unwrap());
@@ -607,7 +607,7 @@ fn literal_strings_many_small_python(bench: &mut Bencher) {
607607
Python::with_gil(|py| {
608608
let validator = build_schema_validator(py, "{'type': 'literal', 'expected': [f'{idx}' for idx in range(100)]}");
609609

610-
let input = py.eval("'99'", None, None).unwrap();
610+
let input = py.eval_bound("'99'", None, None).unwrap();
611611
let input = input.to_object(py).into_bound(py);
612612
let input_str: String = input.extract().unwrap();
613613
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -627,7 +627,7 @@ fn literal_strings_many_large_python(bench: &mut Bencher) {
627627
"{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(100)]}",
628628
);
629629

630-
let input = py.eval("'a' * 25 + '99'", None, None).unwrap();
630+
let input = py.eval_bound("'a' * 25 + '99'", None, None).unwrap();
631631
let input = input.to_object(py).into_bound(py);
632632
let input_str: String = input.extract().unwrap();
633633
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -644,7 +644,7 @@ fn literal_ints_many_json(bench: &mut Bencher) {
644644
Python::with_gil(|py| {
645645
let validator = build_schema_validator(py, "{'type': 'literal', 'expected': list(range(100))}");
646646

647-
let input_json = py.eval("'99'", None, None).unwrap();
647+
let input_json = py.eval_bound("'99'", None, None).unwrap();
648648
let input_json = input_json.to_object(py).into_bound(py);
649649
let result = validator.validate_json(py, &input_json, None, None, None).unwrap();
650650
let result_int: i64 = result.extract(py).unwrap();
@@ -663,9 +663,9 @@ fn literal_strings_many_large_json(bench: &mut Bencher) {
663663
"{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(100)]}",
664664
);
665665

666-
let input = py.eval("'a' * 25 + '99'", None, None).unwrap();
666+
let input = py.eval_bound("'a' * 25 + '99'", None, None).unwrap();
667667
let input = input.to_object(py).into_bound(py);
668-
let input_json = py.eval("'\"' + 'a' * 25 + '99' + '\"'", None, None).unwrap();
668+
let input_json = py.eval_bound("'\"' + 'a' * 25 + '99' + '\"'", None, None).unwrap();
669669
let input_json = input_json.to_object(py).into_bound(py);
670670
let input_str: String = input.extract().unwrap();
671671
let result = validator.validate_json(py, &input_json, None, None, None).unwrap();
@@ -681,7 +681,7 @@ fn literal_strings_many_large_json(bench: &mut Bencher) {
681681
fn literal_mixed_few_python(bench: &mut Bencher) {
682682
Python::with_gil(|py| {
683683
let globals = PyDict::new_bound(py);
684-
py.run(
684+
py.run_bound(
685685
r#"
686686
from enum import Enum
687687
@@ -691,19 +691,19 @@ class Foo(Enum):
691691
v3 = object()
692692
v4 = object()
693693
"#,
694-
Some(globals.as_gil_ref()),
694+
Some(&globals),
695695
None,
696696
)
697697
.unwrap();
698698
let validator = build_schema_validator_with_globals(
699699
py,
700700
"{'type': 'literal', 'expected': [None, 'null', -1, Foo.v4]}",
701-
Some(globals.as_gil_ref()),
701+
Some(&globals),
702702
);
703703

704704
// String
705705
{
706-
let input = py.eval("'null'", None, None).unwrap();
706+
let input = py.eval_bound("'null'", None, None).unwrap();
707707
let input = input.to_object(py).into_bound(py);
708708
let input_str: String = input.extract().unwrap();
709709
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -716,7 +716,7 @@ class Foo(Enum):
716716

717717
// Int
718718
{
719-
let input = py.eval("-1", None, None).unwrap();
719+
let input = py.eval_bound("-1", None, None).unwrap();
720720
let input = input.to_object(py).into_bound(py);
721721
let input_int: i64 = input.extract().unwrap();
722722
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
@@ -729,7 +729,7 @@ class Foo(Enum):
729729

730730
// None
731731
{
732-
let input = py.eval("None", None, None).unwrap();
732+
let input = py.eval_bound("None", None, None).unwrap();
733733
let input = input.to_object(py).into_bound(py);
734734
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
735735
assert!(input.eq(result).unwrap());
@@ -740,7 +740,7 @@ class Foo(Enum):
740740

741741
// Enum
742742
{
743-
let input = py.eval("Foo.v4", Some(globals.as_gil_ref()), None).unwrap();
743+
let input = py.eval_bound("Foo.v4", Some(&globals), None).unwrap();
744744
let input = input.to_object(py).into_bound(py);
745745
let result = validator.validate_python(py, &input, None, None, None, None).unwrap();
746746
assert!(input.eq(result).unwrap());

src/argument_markers.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ impl ArgsKwargs {
3030
#[pymethods]
3131
impl ArgsKwargs {
3232
#[new]
33-
fn py_new(py: Python, args: &PyTuple, kwargs: Option<&PyDict>) -> Self {
33+
fn py_new(py: Python, args: &PyTuple, kwargs: Option<&Bound<'_, PyDict>>) -> Self {
3434
Self {
3535
args: args.into_py(py),
3636
kwargs: match kwargs {
37-
Some(d) if !d.is_empty() => Some(d.into_py(py)),
37+
Some(d) if !d.is_empty() => Some(d.to_owned().unbind()),
3838
_ => None,
3939
},
4040
}
@@ -94,7 +94,7 @@ impl PydanticUndefinedType {
9494
}
9595

9696
#[pyo3(signature = (_memo, /))]
97-
fn __deepcopy__(&self, py: Python, _memo: &PyAny) -> Py<Self> {
97+
fn __deepcopy__(&self, py: Python, _memo: &Bound<'_, PyAny>) -> Py<Self> {
9898
self.__copy__(py)
9999
}
100100

src/errors/types.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub fn list_all_errors(py: Python) -> PyResult<Bound<'_, PyList>> {
4343
}
4444

4545
fn field_from_context<'py, T: FromPyObject<'py>>(
46-
context: Option<&'py PyDict>,
46+
context: Option<&Bound<'py, PyDict>>,
4747
field_name: &str,
4848
enum_name: &str,
4949
type_name_fn: fn() -> &'static str,
@@ -57,7 +57,7 @@ fn field_from_context<'py, T: FromPyObject<'py>>(
5757
}
5858

5959
fn cow_field_from_context<'py, T: FromPyObject<'py>, B: ?Sized + 'static>(
60-
context: Option<&'py PyDict>,
60+
context: Option<&Bound<'py, PyDict>>,
6161
field_name: &str,
6262
enum_name: &str,
6363
_type_name_fn: fn() -> &'static str,
@@ -101,7 +101,7 @@ macro_rules! error_types {
101101
),+,
102102
}
103103
impl ErrorType {
104-
pub fn new(py: Python, value: &str, context: Option<&PyDict>) -> PyResult<Self> {
104+
pub fn new(py: Python, value: &str, context: Option<Bound<'_, PyDict>>) -> PyResult<Self> {
105105
let lookup = ERROR_TYPE_LOOKUP.get_or_init(py, Self::build_lookup);
106106
let error_type = match lookup.get(value) {
107107
Some(error_type) => error_type.clone(),
@@ -111,10 +111,10 @@ macro_rules! error_types {
111111
$(
112112
Self::$item { .. } => {
113113
Ok(Self::$item {
114-
context: context.map(|c| c.into_py(py)),
115114
$(
116-
$key: $ctx_fn(context, stringify!($key), stringify!($item), || stringify!($ctx_type))?,
115+
$key: $ctx_fn(context.as_ref(), stringify!($key), stringify!($item), || stringify!($ctx_type))?,
117116
)*
117+
context: context.map(|c| c.unbind()),
118118
})
119119
},
120120
)+

src/errors/validation_exception.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ impl TryFrom<&Bound<'_, PyAny>> for PyLineError {
478478
.ok_or_else(|| PyKeyError::new_err("type"))?;
479479

480480
let error_type = if let Ok(type_str) = type_raw.downcast::<PyString>() {
481-
let context: Option<&PyDict> = dict.get_as(intern!(py, "ctx"))?;
481+
let context: Option<Bound<'_, PyDict>> = dict.get_as(intern!(py, "ctx"))?;
482482
ErrorType::new(py, type_str.to_str()?, context)?
483483
} else if let Ok(custom_error) = type_raw.extract::<PydanticCustomError>() {
484484
ErrorType::new_custom_error(py, custom_error)

src/errors/value_exception.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ pub struct PydanticCustomError {
6565
#[pymethods]
6666
impl PydanticCustomError {
6767
#[new]
68-
pub fn py_new(py: Python, error_type: String, message_template: String, context: Option<&PyDict>) -> Self {
68+
pub fn py_new(error_type: String, message_template: String, context: Option<Bound<'_, PyDict>>) -> Self {
6969
Self {
7070
error_type,
7171
message_template,
72-
context: context.map(|c| c.into_py(py)),
72+
context: context.map(Bound::unbind),
7373
}
7474
}
7575

@@ -143,7 +143,7 @@ pub struct PydanticKnownError {
143143
#[pymethods]
144144
impl PydanticKnownError {
145145
#[new]
146-
pub fn py_new(py: Python, error_type: &str, context: Option<&PyDict>) -> PyResult<Self> {
146+
pub fn py_new(py: Python, error_type: &str, context: Option<Bound<'_, PyDict>>) -> PyResult<Self> {
147147
let error_type = ErrorType::new(py, error_type, context)?;
148148
Ok(Self { error_type })
149149
}

src/input/datetime.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,11 +562,11 @@ impl TzInfo {
562562
hasher.finish()
563563
}
564564

565-
fn __richcmp__(&self, other: &PyAny, op: CompareOp) -> PyResult<Py<PyAny>> {
565+
fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> PyResult<Py<PyAny>> {
566566
let py = other.py();
567567
if other.is_instance_of::<PyTzInfo>() {
568568
let offset_delta = other.call_method1(intern!(py, "utcoffset"), (py.None(),))?;
569-
if offset_delta.is_none() {
569+
if PyAnyMethods::is_none(&offset_delta) {
570570
return Ok(py.NotImplemented());
571571
}
572572
let offset_seconds: f64 = offset_delta.call_method0(intern!(py, "total_seconds"))?.extract()?;
@@ -577,7 +577,7 @@ impl TzInfo {
577577
}
578578
}
579579

580-
fn __deepcopy__(&self, py: Python, _memo: &PyDict) -> PyResult<Py<Self>> {
580+
fn __deepcopy__(&self, py: Python, _memo: &Bound<'_, PyDict>) -> PyResult<Py<Self>> {
581581
Py::new(py, self.clone())
582582
}
583583

0 commit comments

Comments
 (0)