diff --git a/benches/main.rs b/benches/main.rs index 46b9db5f3..0198c2943 100644 --- a/benches/main.rs +++ b/benches/main.rs @@ -1,8 +1,8 @@ #![feature(test)] -#![allow(deprecated)] // FIXME: just used during upgrading PyO3 to 0.23 extern crate test; +use std::ffi::{CStr, CString}; use test::{black_box, Bencher}; use pyo3::prelude::*; @@ -10,24 +10,28 @@ use pyo3::types::{PyDict, PyString}; use _pydantic_core::{validate_core_schema, SchemaValidator}; -fn build_schema_validator_with_globals(py: Python, code: &str, globals: Option<&Bound<'_, PyDict>>) -> SchemaValidator { - let mut schema = py.eval_bound(code, globals, None).unwrap().extract().unwrap(); +fn build_schema_validator_with_globals( + py: Python, + code: &CStr, + globals: Option<&Bound<'_, PyDict>>, +) -> SchemaValidator { + let mut schema = py.eval(code, globals, None).unwrap().extract().unwrap(); schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); SchemaValidator::py_new(py, &schema, None).unwrap() } -fn build_schema_validator(py: Python, code: &str) -> SchemaValidator { +fn build_schema_validator(py: Python, code: &CStr) -> SchemaValidator { build_schema_validator_with_globals(py, code, None) } fn json<'a>(py: Python<'a>, code: &'a str) -> Bound<'a, PyAny> { - black_box(PyString::new_bound(py, code).into_any()) + black_box(PyString::new(py, code).into_any()) } #[bench] fn ints_json(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'int'}"); + let validator = build_schema_validator(py, c"{'type': 'int'}"); let result = validator .validate_json(py, &json(py, "123"), None, None, None, false.into()) @@ -48,9 +52,9 @@ fn ints_json(bench: &mut Bencher) { #[bench] fn ints_python(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'int'}"); + let validator = build_schema_validator(py, c"{'type': 'int'}"); - let input = 123_i64.into_py(py).into_bound(py); + let Ok(input) = 123_i64.into_pyobject(py); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) .unwrap(); @@ -71,7 +75,7 @@ fn ints_python(bench: &mut Bencher) { #[bench] fn list_int_json(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'list', 'items_schema': {'type': 'int'}}"); + let validator = build_schema_validator(py, c"{'type': 'list', 'items_schema': {'type': 'int'}}"); let code = format!( "[{}]", (0..100).map(|x| x.to_string()).collect::>().join(",") @@ -88,14 +92,15 @@ fn list_int_json(bench: &mut Bencher) { } fn list_int_input(py: Python<'_>) -> (SchemaValidator, PyObject) { - let validator = build_schema_validator(py, "{'type': 'list', 'items_schema': {'type': 'int'}}"); - let code = format!( + let validator = build_schema_validator(py, c"{'type': 'list', 'items_schema': {'type': 'int'}}"); + let code = CString::new(format!( "[{}]", (0..100).map(|x| x.to_string()).collect::>().join(",") - ); + )) + .unwrap(); - let input = py.eval_bound(&code, None, None).unwrap(); - (validator, input.to_object(py)) + let input = py.eval(&code, None, None).unwrap(); + (validator, input.unbind()) } #[bench] @@ -130,7 +135,7 @@ fn list_int_python_isinstance(bench: &mut Bencher) { #[bench] fn list_error_json(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'list', 'items_schema': {'type': 'int'}}"); + let validator = build_schema_validator(py, c"{'type': 'list', 'items_schema': {'type': 'int'}}"); let code = format!( "[{}]", (0..100) @@ -142,7 +147,7 @@ fn list_error_json(bench: &mut Bencher) { match validator.validate_json(py, &json(py, &code), None, None, None, false.into()) { Ok(_) => panic!("unexpectedly valid"), Err(e) => { - let v = e.value_bound(py); + let v = e.value(py); // println!("error: {}", v.to_string()); assert_eq!(v.getattr("title").unwrap().to_string(), "list[int]"); let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap(); @@ -160,28 +165,29 @@ fn list_error_json(bench: &mut Bencher) { } fn list_error_python_input(py: Python<'_>) -> (SchemaValidator, PyObject) { - let validator = build_schema_validator(py, "{'type': 'list', 'items_schema': {'type': 'int'}}"); - let code = format!( + let validator = build_schema_validator(py, c"{'type': 'list', 'items_schema': {'type': 'int'}}"); + let code = CString::new(format!( "[{}]", (0..100) .map(|v| format!(r#""{}""#, as_str(v))) .collect::>() .join(", ") - ); + )) + .unwrap(); - let input = py.eval_bound(&code, None, None).unwrap().extract().unwrap(); + let input = py.eval(&code, None, None).unwrap().extract().unwrap(); match validator.validate_python(py, &input, None, None, None, None, false.into()) { Ok(_) => panic!("unexpectedly valid"), Err(e) => { - let v = e.value_bound(py); + let v = e.value(py); // println!("error: {}", v.to_string()); assert_eq!(v.getattr("title").unwrap().to_string(), "list[int]"); let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap(); assert_eq!(error_count, 100); } }; - (validator, input.to_object(py)) + (validator, input.unbind()) } #[bench] @@ -218,7 +224,7 @@ fn list_error_python_isinstance(bench: &mut Bencher) { #[bench] fn list_any_json(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'list'}"); + let validator = build_schema_validator(py, c"{'type': 'list'}"); let code = format!( "[{}]", (0..100).map(|x| x.to_string()).collect::>().join(",") @@ -237,13 +243,14 @@ fn list_any_json(bench: &mut Bencher) { #[bench] fn list_any_python(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'list'}"); - let code = format!( + let validator = build_schema_validator(py, c"{'type': 'list'}"); + let code = CString::new(format!( "[{}]", (0..100).map(|x| x.to_string()).collect::>().join(",") - ); - let input = py.eval_bound(&code, None, None).unwrap().to_object(py); - let input = black_box(input.bind(py)); + )) + .unwrap(); + let input = py.eval(&code, None, None).unwrap(); + let input = black_box(input); bench.iter(|| { let v = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -266,7 +273,7 @@ fn dict_json(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - "{'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'int'}}", + c"{'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'int'}}", ); let code = format!( @@ -292,18 +299,19 @@ fn dict_python(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - "{'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'int'}}", + c"{'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'int'}}", ); - let code = format!( + let code = CString::new(format!( "{{{}}}", (0..100_u8) .map(|i| format!(r#""{}{}": {i}"#, as_char(i / 26), as_char(i))) .collect::>() .join(", ") - ); - let input = py.eval_bound(&code, None, None).unwrap().to_object(py); - let input = black_box(input.bind(py)); + )) + .unwrap(); + let input = py.eval(&code, None, None).unwrap(); + let input = black_box(input); bench.iter(|| { let v = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -318,27 +326,28 @@ fn dict_value_error(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - r"{ + cr"{ 'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'int', 'lt': 0}, }", ); - let code = format!( + let code = CString::new(format!( "{{{}}}", (0..100_u8) .map(|i| format!(r#""{}": {i}"#, as_str(i))) .collect::>() .join(", ") - ); + )) + .unwrap(); - let input = py.eval_bound(&code, None, None).unwrap().to_object(py).into_bound(py); + let input = py.eval(&code, None, None).unwrap(); match validator.validate_python(py, &input, None, None, None, None, false.into()) { Ok(_) => panic!("unexpectedly valid"), Err(e) => { - let v = e.value_bound(py); + let v = e.value(py); // println!("error: {}", v.to_string()); assert_eq!(v.getattr("title").unwrap().to_string(), "dict[str,constrained-int]"); let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap(); @@ -363,7 +372,7 @@ fn typed_dict_json(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - r"{ + cr"{ 'type': 'typed-dict', 'extra_behavior': 'ignore', 'fields': { @@ -381,12 +390,12 @@ fn typed_dict_json(bench: &mut Bencher) { }", ); - 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(); + let code = r#"{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 0}"#; bench.iter(|| { black_box( validator - .validate_json(py, &json(py, &code), None, None, None, false.into()) + .validate_json(py, &json(py, code), None, None, None, false.into()) .unwrap(), ) }) @@ -398,7 +407,7 @@ fn typed_dict_python(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - r"{ + cr"{ 'type': 'typed-dict', 'extra_behavior': 'ignore', 'fields': { @@ -416,9 +425,9 @@ fn typed_dict_python(bench: &mut Bencher) { }", ); - 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(); - let input = py.eval_bound(&code, None, None).unwrap().to_object(py); - let input = black_box(input.bind(py)); + let code = cr#"{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 0}"#; + let input = py.eval(&code, None, None).unwrap(); + let input = black_box(input); bench.iter(|| { let v = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -433,7 +442,7 @@ fn typed_dict_deep_error(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - r"{ + cr"{ 'type': 'typed-dict', 'fields': { 'field_a': {'type': 'typed-dict-field', 'schema': {'type': 'str'}}, @@ -457,15 +466,15 @@ fn typed_dict_deep_error(bench: &mut Bencher) { }", ); - let code = "{'field_a': '1', 'field_b': {'field_c': '2', 'field_d': {'field_e': '4', 'field_f': 'xx'}}}"; + let code = c"{'field_a': '1', 'field_b': {'field_c': '2', 'field_d': {'field_e': '4', 'field_f': 'xx'}}}"; - let input = py.eval_bound(code, None, None).unwrap().to_object(py); - let input = black_box(input.bind(py)); + let input = py.eval(code, None, None).unwrap(); + let input = black_box(input); match validator.validate_python(py, &input, None, None, None, None, false.into()) { Ok(_) => panic!("unexpectedly valid"), Err(e) => { - let v = e.value_bound(py); + let v = e.value(py); // println!("error: {}", v.to_string()); assert_eq!(v.getattr("title").unwrap().to_string(), "typed-dict"); let error_count: i64 = v.call_method0("error_count").unwrap().extract().unwrap(); @@ -487,10 +496,10 @@ fn typed_dict_deep_error(bench: &mut Bencher) { #[bench] fn complete_model(bench: &mut Bencher) { Python::with_gil(|py| { - let sys_path = py.import_bound("sys").unwrap().getattr("path").unwrap(); + let sys_path = py.import("sys").unwrap().getattr("path").unwrap(); sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap(); - let complete_schema = py.import_bound("complete_schema").unwrap(); + let complete_schema = py.import("complete_schema").unwrap(); let mut schema = complete_schema.call_method0("schema").unwrap(); schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); let validator = SchemaValidator::py_new(py, &schema, None).unwrap(); @@ -511,10 +520,10 @@ fn complete_model(bench: &mut Bencher) { #[bench] fn nested_model_using_definitions(bench: &mut Bencher) { Python::with_gil(|py| { - let sys_path = py.import_bound("sys").unwrap().getattr("path").unwrap(); + let sys_path = py.import("sys").unwrap().getattr("path").unwrap(); sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap(); - let complete_schema = py.import_bound("nested_schema").unwrap(); + let complete_schema = py.import("nested_schema").unwrap(); let mut schema = complete_schema.call_method0("schema_using_defs").unwrap(); schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); let validator = SchemaValidator::py_new(py, &schema, None).unwrap(); @@ -539,10 +548,10 @@ fn nested_model_using_definitions(bench: &mut Bencher) { #[bench] fn nested_model_inlined(bench: &mut Bencher) { Python::with_gil(|py| { - let sys_path = py.import_bound("sys").unwrap().getattr("path").unwrap(); + let sys_path = py.import("sys").unwrap().getattr("path").unwrap(); sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap(); - let complete_schema = py.import_bound("nested_schema").unwrap(); + let complete_schema = py.import("nested_schema").unwrap(); let mut schema = complete_schema.call_method0("inlined_schema").unwrap(); schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); let validator = SchemaValidator::py_new(py, &schema, None).unwrap(); @@ -567,10 +576,9 @@ fn nested_model_inlined(bench: &mut Bencher) { #[bench] fn literal_ints_few_python(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'literal', 'expected': list(range(5))}"); + let validator = build_schema_validator(py, c"{'type': 'literal', 'expected': list(range(5))}"); - let input = 4_i64.into_py(py); - let input = input.bind(py); + let Ok(input) = 4_i64.into_pyobject(py); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) .unwrap(); @@ -591,10 +599,9 @@ fn literal_ints_few_python(bench: &mut Bencher) { #[bench] fn literal_strings_few_small_python(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'literal', 'expected': [f'{idx}' for idx in range(5)]}"); + let validator = build_schema_validator(py, c"{'type': 'literal', 'expected': [f'{idx}' for idx in range(5)]}"); - let input = py.eval_bound("'4'", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"'4'", None, None).unwrap(); let input_str: String = input.extract().unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -618,11 +625,10 @@ fn literal_strings_few_large_python(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - "{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(5)]}", + c"{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(5)]}", ); - let input = py.eval_bound("'a' * 25 + '4'", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"'a' * 25 + '4'", None, None).unwrap(); let input_str: String = input.extract().unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -644,9 +650,9 @@ fn literal_strings_few_large_python(bench: &mut Bencher) { #[bench] fn literal_enums_few_python(bench: &mut Bencher) { Python::with_gil(|py| { - let globals = PyDict::new_bound(py); - py.run_bound( - r" + let globals = PyDict::new(py); + py.run( + cr" from enum import Enum class Foo(Enum): @@ -662,12 +668,11 @@ class Foo(Enum): let validator = build_schema_validator_with_globals( py, - "{'type': 'literal', 'expected': [Foo.v1, Foo.v2, Foo.v3, Foo.v4]}", + c"{'type': 'literal', 'expected': [Foo.v1, Foo.v2, Foo.v3, Foo.v4]}", Some(&globals), ); - let input = py.eval_bound("Foo.v4", Some(&globals), None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"Foo.v4", Some(&globals), None).unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) .unwrap(); @@ -687,9 +692,9 @@ class Foo(Enum): #[bench] fn literal_ints_many_python(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'literal', 'expected': list(range(100))}"); + let validator = build_schema_validator(py, c"{'type': 'literal', 'expected': list(range(100))}"); - let input = 99_i64.into_py(py).into_bound(py); + let Ok(input) = 99_i64.into_pyobject(py); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) .unwrap(); @@ -710,10 +715,10 @@ fn literal_ints_many_python(bench: &mut Bencher) { #[bench] fn literal_strings_many_small_python(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'literal', 'expected': [f'{idx}' for idx in range(100)]}"); + let validator = + build_schema_validator(py, c"{'type': 'literal', 'expected': [f'{idx}' for idx in range(100)]}"); - let input = py.eval_bound("'99'", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"'99'", None, None).unwrap(); let input_str: String = input.extract().unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -737,11 +742,10 @@ fn literal_strings_many_large_python(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - "{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(100)]}", + c"{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(100)]}", ); - let input = py.eval_bound("'a' * 25 + '99'", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"'a' * 25 + '99'", None, None).unwrap(); let input_str: String = input.extract().unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -763,10 +767,9 @@ fn literal_strings_many_large_python(bench: &mut Bencher) { #[bench] fn literal_ints_many_json(bench: &mut Bencher) { Python::with_gil(|py| { - let validator = build_schema_validator(py, "{'type': 'literal', 'expected': list(range(100))}"); + let validator = build_schema_validator(py, c"{'type': 'literal', 'expected': list(range(100))}"); - let input_json = py.eval_bound("'99'", None, None).unwrap(); - let input_json = input_json.to_object(py).into_bound(py); + let input_json = py.eval(c"'99'", None, None).unwrap(); let result = validator .validate_json(py, &input_json, None, None, None, false.into()) .unwrap(); @@ -789,13 +792,11 @@ fn literal_strings_many_large_json(bench: &mut Bencher) { Python::with_gil(|py| { let validator = build_schema_validator( py, - "{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(100)]}", + c"{'type': 'literal', 'expected': ['a' * 25 + f'{idx}' for idx in range(100)]}", ); - let input = py.eval_bound("'a' * 25 + '99'", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); - let input_json = py.eval_bound("'\"' + 'a' * 25 + '99' + '\"'", None, None).unwrap(); - let input_json = input_json.to_object(py).into_bound(py); + let input = py.eval(c"'a' * 25 + '99'", None, None).unwrap(); + let input_json = py.eval(c"'\"' + 'a' * 25 + '99' + '\"'", None, None).unwrap(); let input_str: String = input.extract().unwrap(); let result = validator .validate_json(py, &input_json, None, None, None, false.into()) @@ -817,9 +818,9 @@ fn literal_strings_many_large_json(bench: &mut Bencher) { #[bench] fn literal_mixed_few_python(bench: &mut Bencher) { Python::with_gil(|py| { - let globals = PyDict::new_bound(py); - py.run_bound( - r" + let globals = PyDict::new(py); + py.run( + cr" from enum import Enum class Foo(Enum): @@ -834,14 +835,13 @@ class Foo(Enum): .unwrap(); let validator = build_schema_validator_with_globals( py, - "{'type': 'literal', 'expected': [None, 'null', -1, Foo.v4]}", + c"{'type': 'literal', 'expected': [None, 'null', -1, Foo.v4]}", Some(&globals), ); // String { - let input = py.eval_bound("'null'", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"'null'", None, None).unwrap(); let input_str: String = input.extract().unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -861,8 +861,7 @@ class Foo(Enum): // Int { - let input = py.eval_bound("-1", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"-1", None, None).unwrap(); let input_int: i64 = input.extract().unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) @@ -882,8 +881,7 @@ class Foo(Enum): // None { - let input = py.eval_bound("None", None, None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"None", None, None).unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) .unwrap(); @@ -901,8 +899,7 @@ class Foo(Enum): // Enum { - let input = py.eval_bound("Foo.v4", Some(&globals), None).unwrap(); - let input = input.to_object(py).into_bound(py); + let input = py.eval(c"Foo.v4", Some(&globals), None).unwrap(); let result = validator .validate_python(py, &input, None, None, None, None, false.into()) .unwrap(); diff --git a/tests/test.rs b/tests/test.rs index 1b5beb0fe..b59fbec54 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,8 +1,7 @@ -#![allow(deprecated)] // FIXME: just used during upgrading PyO3 to 0.23 - #[cfg(test)] mod tests { use _pydantic_core::{SchemaSerializer, SchemaValidator, WarningsArg}; + use pyo3::ffi::c_str; // can switch to c"" literals on MSRV >= 1.77 use pyo3::prelude::*; use pyo3::types::PyDict; @@ -24,7 +23,8 @@ mod tests { // 'type': 'function-wrap', // 'function': lambda: None, // }, - let code = r"{ + let code = c_str!( + r"{ 'type': 'definitions', 'schema': {'type': 'definition-ref', 'schema_ref': 'C-ref'}, 'definitions': [ @@ -46,8 +46,9 @@ mod tests { }, }, ] - }"; - let schema: Bound<'_, PyDict> = py.eval_bound(code, None, None).unwrap().extract().unwrap(); + }" + ); + let schema: Bound<'_, PyDict> = py.eval(code, None, None).unwrap().extract().unwrap(); SchemaSerializer::py_new(schema, None).unwrap(); }); } @@ -55,7 +56,8 @@ mod tests { #[test] fn test_serialize_computed_fields() { Python::with_gil(|py| { - let code = r#" + let code = c_str!( + r#" class A: @property def b(self) -> str: @@ -74,9 +76,10 @@ schema = { "type": "model", } a = A() - "#; - let locals = PyDict::new_bound(py); - py.run_bound(code, None, Some(&locals)).unwrap(); + "# + ); + let locals = PyDict::new(py); + py.run(code, None, Some(&locals)).unwrap(); let a = locals.get_item("a").unwrap().unwrap(); let schema = locals .get_item("schema") @@ -111,7 +114,8 @@ a = A() #[test] fn test_literal_schema() { Python::with_gil(|py| { - let code = r#" + let code = c_str!( + r#" schema = { "type": "dict", "keys_schema": { @@ -124,9 +128,10 @@ schema = { "strict": False, } json_input = '{"a": "something"}' - "#; - let locals = PyDict::new_bound(py); - py.run_bound(code, None, Some(&locals)).unwrap(); + "# + ); + let locals = PyDict::new(py); + py.run(code, None, Some(&locals)).unwrap(); let schema = locals.get_item("schema").unwrap().unwrap(); let json_input = locals.get_item("json_input").unwrap().unwrap(); let binding = SchemaValidator::py_new(py, &schema, None) @@ -142,7 +147,8 @@ json_input = '{"a": "something"}' #[test] fn test_segfault_for_recursive_schemas() { Python::with_gil(|py| { - let code = r" + let code = c_str!( + r" schema = { 'type': 'definitions', 'schema': { @@ -177,9 +183,10 @@ schema = { } dump_json_input_1 = 1 dump_json_input_2 = {'a': 'something'} - "; - let locals = PyDict::new_bound(py); - py.run_bound(code, None, Some(&locals)).unwrap(); + " + ); + let locals = PyDict::new(py); + py.run(code, None, Some(&locals)).unwrap(); let schema = locals .get_item("schema") .unwrap()