Skip to content

Commit 5e6df2d

Browse files
authored
Cow<[u8]> FromPyObject impl: allow any Sequence[int] (#5667)
Simplifies the type hint: bytes and bytearray are Sequence[int] Allows to drop INPUT_SEQUENCE_TYPE
1 parent e8e5a50 commit 5e6df2d

File tree

7 files changed

+17
-34
lines changed

7 files changed

+17
-34
lines changed

newsfragments/5667.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`FromPyObject` on `Cow<[u8]>` allow any `Sequence[int]` and change the error type to `PyErr`

pytests/stubs/buf_and_str.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class BytesExtractor:
1313
@staticmethod
1414
def from_str_lossy(string: str) -> int: ...
1515

16-
def map_byte_cow(bytes: bytes | bytearray) -> bytes: ...
16+
def map_byte_cow(bytes: Sequence[int]) -> bytes: ...
1717
def map_byte_slice(bytes: bytes) -> bytes: ...
18-
def map_byte_vec(bytes: bytes | bytearray | Sequence[int]) -> bytes: ...
18+
def map_byte_vec(bytes: Sequence[int]) -> bytes: ...
1919
def return_memoryview() -> memoryview: ...

src/conversion.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use crate::inspect::types::TypeInfo;
77
use crate::inspect::TypeHint;
88
use crate::pyclass::boolean_struct::False;
99
use crate::pyclass::{PyClassGuardError, PyClassGuardMutError};
10-
use crate::types::PyTuple;
1110
#[cfg(feature = "experimental-inspect")]
12-
use crate::types::{PyList, PySequence};
11+
use crate::types::PyList;
12+
use crate::types::PyTuple;
1313
use crate::{
1414
Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyClassGuard, PyErr, PyRef, PyRefMut,
1515
PyTypeCheck, Python,
@@ -463,12 +463,6 @@ pub trait FromPyObject<'a, 'py>: Sized {
463463
Option::<NeverASequence<Self>>::None
464464
}
465465

466-
/// The union of Sequence[Self::INPUT_TYPE] and the input sequence extraction function [`FromPyObject::sequence_extractor`] if it's defined
467-
#[cfg(feature = "experimental-inspect")]
468-
#[doc(hidden)]
469-
const SEQUENCE_INPUT_TYPE: TypeHint =
470-
TypeHint::subscript(&PySequence::TYPE_HINT, &[Self::INPUT_TYPE]);
471-
472466
/// Helper used to make a specialized path in extracting `DateTime<Tz>` where `Tz` is
473467
/// `chrono::Local`, which will accept "naive" datetime objects as being in the local timezone.
474468
#[cfg(feature = "chrono-local")]

src/conversions/std/array.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ where
5151
type Error = PyErr;
5252

5353
#[cfg(feature = "experimental-inspect")]
54-
const INPUT_TYPE: TypeHint = T::SEQUENCE_INPUT_TYPE;
54+
const INPUT_TYPE: TypeHint = TypeHint::subscript(&PySequence::TYPE_HINT, &[T::INPUT_TYPE]);
5555

5656
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
5757
if let Some(extractor) = T::sequence_extractor(obj, crate::conversion::private::Token) {

src/conversions/std/num.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use crate::inspect::TypeHint;
88
use crate::py_result_ext::PyResultExt;
99
#[cfg(feature = "experimental-inspect")]
1010
use crate::type_object::PyTypeInfo;
11-
#[cfg(feature = "experimental-inspect")]
12-
use crate::types::PySequence;
1311
use crate::types::{PyByteArray, PyByteArrayMethods, PyBytes, PyInt};
1412
use crate::{exceptions, ffi, Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, Python};
1513
use std::convert::Infallible;
@@ -322,13 +320,6 @@ impl<'py> FromPyObject<'_, 'py> for u8 {
322320
None
323321
}
324322
}
325-
326-
#[cfg(feature = "experimental-inspect")]
327-
const SEQUENCE_INPUT_TYPE: TypeHint = TypeHint::union(&[
328-
PyBytes::TYPE_HINT,
329-
PyByteArray::TYPE_HINT,
330-
TypeHint::subscript(&PySequence::TYPE_HINT, &[Self::INPUT_TYPE]),
331-
]);
332323
}
333324

334325
pub(crate) enum BytesSequenceExtractor<'a, 'py> {

src/conversions/std/slice.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use crate::inspect::TypeHint;
77
#[cfg(feature = "experimental-inspect")]
88
use crate::type_object::PyTypeInfo;
99
use crate::{
10-
conversion::IntoPyObject,
11-
types::{PyByteArray, PyByteArrayMethods, PyBytes},
12-
Bound, CastError, PyAny, PyErr, Python,
10+
conversion::IntoPyObject, types::PyBytes, Bound, CastError, PyAny, PyErr, PyResult, Python,
1311
};
1412

1513
impl<'a, 'py, T> IntoPyObject<'py> for &'a [T]
@@ -63,18 +61,17 @@ impl<'a, 'py> crate::conversion::FromPyObject<'a, 'py> for &'a [u8] {
6361
/// pointing into the source object, and no copying or heap allocations will happen.
6462
/// If it is a `bytearray`, its contents will be copied to an owned `Cow`.
6563
impl<'a, 'py> crate::conversion::FromPyObject<'a, 'py> for Cow<'a, [u8]> {
66-
type Error = CastError<'a, 'py>;
64+
type Error = PyErr;
6765

6866
#[cfg(feature = "experimental-inspect")]
69-
const INPUT_TYPE: TypeHint = TypeHint::union(&[PyBytes::TYPE_HINT, PyByteArray::TYPE_HINT]);
70-
71-
fn extract(ob: crate::Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
72-
if let Ok(bytes) = ob.cast::<PyBytes>() {
73-
return Ok(Cow::Borrowed(bytes.as_bytes()));
74-
}
75-
76-
let byte_array = ob.cast::<PyByteArray>()?;
77-
Ok(Cow::Owned(byte_array.to_vec()))
67+
const INPUT_TYPE: TypeHint = Vec::<u8>::INPUT_TYPE;
68+
69+
fn extract(ob: crate::Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {
70+
Ok(if let Ok(bytes) = ob.cast::<PyBytes>() {
71+
Cow::Borrowed(bytes.as_bytes()) // It's immutable, we can take a slice
72+
} else {
73+
Cow::Owned(Vec::extract(ob)?) // Not possible to take a slice, we have to build a Vec<u8>
74+
})
7875
}
7976

8077
#[cfg(feature = "experimental-inspect")]

src/conversions/std/vec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ where
6969
type Error = PyErr;
7070

7171
#[cfg(feature = "experimental-inspect")]
72-
const INPUT_TYPE: TypeHint = T::SEQUENCE_INPUT_TYPE;
72+
const INPUT_TYPE: TypeHint = TypeHint::subscript(&PySequence::TYPE_HINT, &[T::INPUT_TYPE]);
7373

7474
fn extract(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
7575
if let Some(extractor) = T::sequence_extractor(obj, crate::conversion::private::Token) {

0 commit comments

Comments
 (0)