Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,8 @@ too_many_lines = "allow"
unnecessary_wraps = "allow"
unused_self = "allow"
used_underscore_binding = "allow"

[patch.crates-io]
pyo3 = { git = "https://github.com/pyo3/pyo3.git" }
pyo3-build-config = { git = "https://github.com/pyo3/pyo3.git" }
jiter = { git = "https://github.com/pydantic/jiter.git", branch = "dh/pyo3-0.27" }
6 changes: 3 additions & 3 deletions src/build_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::str::FromStr;
use pyo3::exceptions::PyException;
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyList, PyString};
use pyo3::{intern, FromPyObject, PyErrArguments};
use pyo3::{intern, PyErrArguments};

use crate::errors::{PyLineError, ValError};
use crate::input::InputType;
Expand All @@ -19,7 +19,7 @@ pub fn schema_or_config<'py, T>(
config_key: &Bound<'py, PyString>,
) -> PyResult<Option<T>>
where
T: FromPyObject<'py>,
T: FromPyObjectOwned<'py>,
{
match schema.get_as(schema_key)? {
Some(v) => Ok(Some(v)),
Expand All @@ -36,7 +36,7 @@ pub fn schema_or_config_same<'py, T>(
key: &Bound<'py, PyString>,
) -> PyResult<Option<T>>
where
T: FromPyObject<'py>,
T: FromPyObjectOwned<'py>,
{
schema_or_config(schema, config, key, key)
}
Expand Down
12 changes: 7 additions & 5 deletions src/errors/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn list_all_errors(py: Python<'_>) -> PyResult<Bound<'_, PyList>> {
PyList::new(py, errors)
}

fn field_from_context<'py, T: FromPyObject<'py>>(
fn field_from_context<'py, T: FromPyObjectOwned<'py>>(
context: Option<&Bound<'py, PyDict>>,
field_name: &str,
enum_name: &str,
Expand All @@ -56,7 +56,7 @@ fn field_from_context<'py, T: FromPyObject<'py>>(
.map_err(|_| py_error_type!(PyTypeError; "{}: '{}' context value must be a {}", enum_name, field_name, type_name_fn()))
}

fn cow_field_from_context<'py, T: FromPyObject<'py>, B: ToOwned<Owned = T> + ?Sized + 'static>(
fn cow_field_from_context<'py, T: FromPyObjectOwned<'py>, B: ToOwned<Owned = T> + ?Sized + 'static>(
context: Option<&Bound<'py, PyDict>>,
field_name: &str,
enum_name: &str,
Expand Down Expand Up @@ -805,9 +805,11 @@ impl From<Int> for Number {
}
}

impl FromPyObject<'_> for Number {
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
if let Some(int) = extract_i64(obj) {
impl FromPyObject<'_, '_> for Number {
type Error = PyErr;

fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
if let Some(int) = extract_i64(&obj) {
Ok(Number::Int(int))
} else if let Ok(float) = obj.extract::<f64>() {
Ok(Number::Float(float))
Expand Down
8 changes: 5 additions & 3 deletions src/input/return_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,9 +706,11 @@ impl Rem for &Int {
}
}

impl FromPyObject<'_> for Int {
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
match extract_int(obj) {
impl FromPyObject<'_, '_> for Int {
type Error = PyErr;

fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
match extract_int(&obj) {
Some(i) => Ok(i),
None => py_err!(PyTypeError; "Expected int, got {}", obj.get_type()),
}
Expand Down
5 changes: 3 additions & 2 deletions src/serializers/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,9 @@ pub fn utf8_py_error(py: Python, err: Utf8Error, data: &[u8]) -> PyErr {
}
}

impl FromPyObject<'_> for InfNanMode {
fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> {
impl FromPyObject<'_, '_> for InfNanMode {
type Error = PyErr;
fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
Self::from_str(ob.downcast::<PyString>()?.to_str()?)
}
}
6 changes: 4 additions & 2 deletions src/serializers/extra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,10 @@ pub enum WarningsMode {
Error,
}

impl<'py> FromPyObject<'py> for WarningsMode {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<WarningsMode> {
impl<'py> FromPyObject<'_, 'py> for WarningsMode {
type Error = PyErr;

fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<WarningsMode> {
if let Ok(bool_mode) = ob.downcast::<PyBool>() {
Ok(bool_mode.is_true().into())
} else if let Ok(str_mode) = ob.extract::<&str>() {
Expand Down
18 changes: 9 additions & 9 deletions src/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@ use core::fmt;
use num_bigint::BigInt;

use pyo3::exceptions::PyKeyError;
use pyo3::intern;
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyString};
use pyo3::{intern, FromPyObject};

use crate::input::Int;
use jiter::{cached_py_string, StringCacheMode};

pub trait SchemaDict<'py> {
fn get_as<T>(&self, key: &Bound<'py, PyString>) -> PyResult<Option<T>>
where
T: FromPyObject<'py>;
T: FromPyObjectOwned<'py>;

fn get_as_req<T>(&self, key: &Bound<'py, PyString>) -> PyResult<T>
where
T: FromPyObject<'py>;
T: FromPyObjectOwned<'py>;
}

impl<'py> SchemaDict<'py> for Bound<'py, PyDict> {
fn get_as<T>(&self, key: &Bound<'py, PyString>) -> PyResult<Option<T>>
where
T: FromPyObject<'py>,
T: FromPyObjectOwned<'py>,
{
match self.get_item(key)? {
Some(t) => t.extract().map(Some),
Some(t) => t.extract().map_err(Into::into).map(Some),
None => Ok(None),
}
}

fn get_as_req<T>(&self, key: &Bound<'py, PyString>) -> PyResult<T>
where
T: FromPyObject<'py>,
T: FromPyObjectOwned<'py>,
{
match self.get_item(key)? {
Some(t) => t.extract(),
Some(t) => t.extract().map_err(Into::into),
None => py_err!(PyKeyError; "{}", key),
}
}
Expand All @@ -45,7 +45,7 @@ impl<'py> SchemaDict<'py> for Bound<'py, PyDict> {
impl<'py> SchemaDict<'py> for Option<&Bound<'py, PyDict>> {
fn get_as<T>(&self, key: &Bound<'py, PyString>) -> PyResult<Option<T>>
where
T: FromPyObject<'py>,
T: FromPyObjectOwned<'py>,
{
match self {
Some(d) => d.get_as(key),
Expand All @@ -56,7 +56,7 @@ impl<'py> SchemaDict<'py> for Option<&Bound<'py, PyDict>> {
#[cfg_attr(has_coverage_attribute, coverage(off))]
fn get_as_req<T>(&self, key: &Bound<'py, PyString>) -> PyResult<T>
where
T: FromPyObject<'py>,
T: FromPyObjectOwned<'py>,
{
match self {
Some(d) => d.get_as_req(key),
Expand Down
10 changes: 6 additions & 4 deletions src/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl PyUrl {
let schema_obj = SCHEMA_DEFINITION_URL
.get_or_init(py, || build_schema_validator(py, "url"))
.validate_python(py, url, None, None, None, None, None, false.into(), None, None)?;
schema_obj.extract(py)
schema_obj.extract(py).map_err(Into::into)
}

#[getter]
Expand Down Expand Up @@ -226,7 +226,7 @@ impl PyMultiHostUrl {
let schema_obj = SCHEMA_DEFINITION_MULTI_HOST_URL
.get_or_init(py, || build_schema_validator(py, "multi-host-url"))
.validate_python(py, url, None, None, None, None, None, false.into(), None, None)?;
schema_obj.extract(py)
schema_obj.extract(py).map_err(Into::into)
}

#[getter]
Expand Down Expand Up @@ -436,8 +436,10 @@ impl UrlHostParts {
}
}

impl FromPyObject<'_> for UrlHostParts {
fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> {
impl FromPyObject<'_, '_> for UrlHostParts {
type Error = PyErr;

fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
let py = ob.py();
let dict = ob.downcast::<PyDict>()?;
Ok(UrlHostParts {
Expand Down
8 changes: 1 addition & 7 deletions src/validators/uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,8 @@ const UUID_IS_SAFE: &str = "is_safe";

static UUID_TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();

fn import_type(py: Python, module: &str, attr: &str) -> PyResult<Py<PyType>> {
py.import(module)?.getattr(attr)?.extract()
}

fn get_uuid_type(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {
Ok(UUID_TYPE
.get_or_init(py, || import_type(py, "uuid", "UUID").unwrap())
.bind(py))
UUID_TYPE.import(py, "uuid", "UUID")
}

#[derive(Debug, Clone, Copy)]
Expand Down
Loading