From 8e4a11b88f8843ded82a5883b44b5c540f16a68c Mon Sep 17 00:00:00 2001 From: Kirill Kuzminykh Date: Wed, 26 Oct 2022 21:53:16 +0400 Subject: [PATCH] - Fixed metadata of package. - Added building of wheel for Python 3.11. - Updated version of ``libheif-rs`` to 0.15.1. - Updated version of ``pyo3`` to 0.17.2. --- CHANGES.rst | 13 ++- Cargo.lock | 132 +++++++++++++++++------------ Cargo.toml | 5 +- README.rst | 2 +- docker/Dockerfile | 2 +- docker/build.sh | 3 +- pyproject.toml | 6 +- src/stream.rs | 210 +++++++++++++++++++++++----------------------- 8 files changed, 203 insertions(+), 170 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index e5a0340..9b0455e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,8 +15,19 @@ CHANGELOG ********* +0.13 (2022-10-26) +================= + +Changes +------- + +- Fixed metadata of package. +- Added building of wheel for Python 3.11. +- Updated version of ``libheif-rs`` to 0.15.1. +- Updated version of ``pyo3`` to 0.17.2. + 0.12 (2022-05-20) -=================== +================= Breaking Changes ---------------- diff --git a/Cargo.lock b/Cargo.lock index 139a837..e2db019 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "enumn" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052bc8773a98bd051ff37db74a8a25f00e6bfa2cbd03373390c72e9f7afbf344" +checksum = "038b1afa59052df211f9efd58f8b1d84c242935ede1c3dbaed26b018a9e06ae2" dependencies = [ "proc-macro2", "quote", @@ -33,21 +33,21 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a0bd019339e5d968b37855180087b7b9d512c5046fbd244cf8c95687927d6e" +checksum = "adab1eaa3408fb7f0c777a73e7465fd5656136fc93b670eb6df3c88c2c1344e3" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "55edcf6c0bb319052dea84732cf99db461780fd5e8d3eb46ab6ff312ab31f197" [[package]] name = "libheif-rs" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a28e98f7e0b934f2d240bbd438b02d82d2bbce34a97d5cf25767e2c2ff249f7" +checksum = "edf58b5301fc9c13d446e2a75e363ebf848f624ab7026d5cda567b11a6f21056" dependencies = [ "enumn", "libheif-sys", @@ -64,25 +64,34 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" -version = "1.11.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "parking_lot" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", "parking_lot_core", @@ -90,9 +99,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ "cfg-if", "libc", @@ -103,22 +112,23 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.16.5" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6302e85060011447471887705bb7838f14aba43fcb06957d823739a496b3dc" +checksum = "201b6887e5576bf2f945fe65172c1fcbf3fcf285b23e4d71eb171d9736e38d32" dependencies = [ "cfg-if", "indoc", "libc", + "memoffset", "parking_lot", "pyo3-build-config", "pyo3-ffi", @@ -128,9 +138,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.16.5" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b65b546c35d8a3b1b2f0ddbac7c6a569d759f357f2b9df884f5d6b719152c8" +checksum = "bf0708c9ed01692635cbf056e286008e5a2927ab1a5e48cdd3aeb1ba5a6fef47" dependencies = [ "once_cell", "target-lexicon", @@ -138,9 +148,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.16.5" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c275a07127c1aca33031a563e384ffdd485aee34ef131116fcd58e3430d1742b" +checksum = "90352dea4f486932b72ddf776264d293f85b79a1d214de1d023927b41461132d" dependencies = [ "libc", "pyo3-build-config", @@ -148,9 +158,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.16.5" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284fc4485bfbcc9850a6d661d627783f18d19c2ab55880b021671c4ba83e90f7" +checksum = "7eb24b804a2d9e88bfcc480a5a6dd76f006c1e3edaf064e8250423336e2cd79d" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -160,9 +170,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.16.5" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bda0f58f73f5c5429693c96ed57f7abdb38fdfc28ae06da4101a257adb7faf" +checksum = "f22bb49f6a7348c253d7ac67a6875f2dc65f36c2ae64a82c381d528972bea6d6" dependencies = [ "proc-macro2", "quote", @@ -171,18 +181,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -203,15 +213,15 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "smallvec" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.95" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -220,61 +230,75 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1" +checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unindent" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52fee519a3e570f7df377a06a1a7775cdbfb7aa460be7e08de2b1f0e69973a44" +checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/Cargo.toml b/Cargo.toml index 4c37de4..0785707 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "rust_lib" version = "0.7.0" authors = ["Kirill Kuzminykh "] +homepage = "https://github.com/Cykooz/cykooz.heif" edition = "2021" @@ -15,8 +16,8 @@ name = "cykooz.heif.rust_lib" [dependencies] -libheif-rs = "0.15" -pyo3 = { version = "0.16.5", features = ["extension-module"] } +libheif-rs = "0.15.1" +pyo3 = { version = "0.17.2", features = ["extension-module"] } [profile.release] diff --git a/README.rst b/README.rst index 7db5f18..d7f3baf 100644 --- a/README.rst +++ b/README.rst @@ -6,7 +6,7 @@ cykooz.heif ``RawHeifImage`` is a simple wrapper around low level HEIF-decoder. -`CHANGELOG `_ +`CHANGELOG `_ Usage Examples ============== diff --git a/docker/Dockerfile b/docker/Dockerfile index fc22665..12c6f8e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -117,7 +117,7 @@ RUN mkdir /workdir "${CARGO_TARGET_DIR}" RUN set -ex \ && source $HOME/.cargo/env \ - && declare -a pythons=("cp37-cp37m" "cp38-cp38" "cp39-cp39" "cp310-cp310") \ + && declare -a pythons=("cp37-cp37m" "cp38-cp38" "cp39-cp39" "cp310-cp310" "cp311-cp311") \ && for PY in "${pythons[@]}"; do \ cd "/opt/python/${PY}/bin/" \ && ./pip install --upgrade pip auditwheel twine setuptools maturin \ diff --git a/docker/build.sh b/docker/build.sh index a0d3a9e..3f09b29 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -28,7 +28,7 @@ rm -rf docker tests bootstrap.py build_wheels.sh source "$HOME/.cargo/env" -PYTHONS=("7" "8" "9" "10") +PYTHONS=("7" "8" "9" "10" "11") mkdir "${RESULT}/repaired" for PY_MINOR in "${PYTHONS[@]}"; do PY="3${PY_MINOR}" @@ -42,7 +42,6 @@ for PY_MINOR in "${PYTHONS[@]}"; do mkdir "${RESULT}/wheelhouse${PY}" PYTHON_SYS_EXECUTABLE="${PY_BIN_DIR}/python" "${PY_BIN_DIR}/maturin" build \ --release --strip \ - --no-sdist \ --compatibility manylinux_2_24 \ --skip-auditwheel \ -i "python3.${PY_MINOR}" \ diff --git a/pyproject.toml b/pyproject.toml index d0e805a..2c9296f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "maturin" [project] name = "cykooz.heif" -version = "0.12" +version = "0.13" description = "A decoder of HEIF format of images" readme = "README.rst" classifiers = [ @@ -16,6 +16,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Rust", "Topic :: Multimedia :: Graphics", @@ -24,9 +25,6 @@ classifiers = [ ] keywords = ["heif", "heic", "libheif", "pil", "pillow"] requires-python = ">=3.7" -url = "https://github.com/Cykooz/cykooz.heif" -author = "Kirill Kuzminykh" -author_email = "cykooz@gmail.com" [project.optional-dependencies] diff --git a/src/stream.rs b/src/stream.rs index 61eb265..6f1a929 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -1,6 +1,7 @@ +use std::io; + use pyo3::prelude::*; use pyo3::types::PyBytes; -use std::io; pub(crate) struct StreamFromPy { pub(crate) py_stream: PyObject, @@ -8,137 +9,136 @@ pub(crate) struct StreamFromPy { impl io::Read for StreamFromPy { fn read(&mut self, buf: &mut [u8]) -> io::Result { - let gil = Python::acquire_gil(); - let py = gil.python(); - match self.py_stream.call_method1(py, "read", (buf.len(),)) { - Ok(v) => { - let py_bytes: &PyBytes = v.cast_as(py).map_err(|_| { - io::Error::new( - io::ErrorKind::Other, - "Error during casting PyObject into PyBytes \ + Python::with_gil(|py| { + match self.py_stream.call_method1(py, "read", (buf.len(), )) { + Ok(v) => { + let py_bytes: &PyBytes = v.cast_as(py).map_err(|_| { + io::Error::new( + io::ErrorKind::Other, + "Error during casting PyObject into PyBytes \ ('read' method returns not a bytes)", - ) - })?; - let bytes = py_bytes.as_bytes(); - if !bytes.is_empty() { - buf[..bytes.len()].copy_from_slice(bytes); + ) + })?; + let bytes = py_bytes.as_bytes(); + if !bytes.is_empty() { + buf[..bytes.len()].copy_from_slice(bytes); + } + Ok(bytes.len()) + } + Err(e) => { + let err_str: String = e + .to_object(py) + .call_method0(py, "__str__") + .unwrap() + .extract(py) + .unwrap(); + Err(io::Error::new(io::ErrorKind::Other, err_str)) } - Ok(bytes.len()) - } - Err(e) => { - let err_str: String = e - .to_object(py) - .call_method0(py, "__str__") - .unwrap() - .extract(py) - .unwrap(); - Err(io::Error::new(io::ErrorKind::Other, err_str)) } - } + }) } } impl io::Seek for StreamFromPy { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { - let gil = Python::acquire_gil(); - let py = gil.python(); - let (whence, offset) = match pos { io::SeekFrom::Start(offset) => (0, offset as i64), io::SeekFrom::Current(offset) => (1, offset), io::SeekFrom::End(offset) => (2, offset), }; - match self.py_stream.call_method1(py, "seek", (offset, whence)) { - Ok(v) => { - let pos: u64 = v.extract(py).map_err(|_| { - io::Error::new(io::ErrorKind::Other, "Method 'seek' returns not u64") - })?; - Ok(pos) - } - Err(e) => { - let err_str: String = e - .to_object(py) - .call_method0(py, "__str__") - .unwrap() - .extract(py) - .unwrap(); - Err(io::Error::new(io::ErrorKind::Other, err_str)) + Python::with_gil(|py| { + match self.py_stream.call_method1(py, "seek", (offset, whence)) { + Ok(v) => { + let pos: u64 = v.extract(py).map_err(|_| { + io::Error::new(io::ErrorKind::Other, "Method 'seek' returns not u64") + })?; + Ok(pos) + } + Err(e) => { + let err_str: String = e + .to_object(py) + .call_method0(py, "__str__") + .unwrap() + .extract(py) + .unwrap(); + Err(io::Error::new(io::ErrorKind::Other, err_str)) + } } - } + }) } } #[cfg(test)] mod tests { - use super::*; - use pyo3::types::IntoPyDict; use std::io::{Read, Seek}; - #[test] - fn test_read() -> PyResult<()> { - let gil = Python::acquire_gil(); - let py = gil.python(); - - let locals = [("io", py.import("io")?)].into_py_dict(py); - let code = "io.BytesIO(b'a' * 100 + b'b' * 50)"; - let result = py.eval(code, None, Some(&locals))?; - let mut stream_from_py = StreamFromPy { - py_stream: result.into_py(py), - }; - let mut buf = vec![0u8; 100]; - - let size = stream_from_py.read(&mut buf)?; - assert_eq!(size, 100); - assert_eq!(buf, vec![b'a'; 100]); - - let size = stream_from_py.read(&mut buf)?; - assert_eq!(size, 50); - let mut expect = vec![b'b'; 50]; - expect.append(&mut vec![b'a'; 50]); - assert_eq!(buf, expect); + use pyo3::types::IntoPyDict; - let size = stream_from_py.read(&mut buf)?; - assert_eq!(size, 0); - assert_eq!(buf, expect); + use super::*; - Ok(()) + #[test] + fn test_read() -> PyResult<()> { + Python::with_gil(|py| { + let locals = [("io", py.import("io")?)].into_py_dict(py); + let code = "io.BytesIO(b'a' * 100 + b'b' * 50)"; + let result = py.eval(code, None, Some(locals))?; + let mut stream_from_py = StreamFromPy { + py_stream: result.into_py(py), + }; + let mut buf = vec![0u8; 100]; + + let size = stream_from_py.read(&mut buf)?; + assert_eq!(size, 100); + assert_eq!(buf, vec![b'a'; 100]); + + let size = stream_from_py.read(&mut buf)?; + assert_eq!(size, 50); + let mut expect = vec![b'b'; 50]; + expect.append(&mut vec![b'a'; 50]); + assert_eq!(buf, expect); + + let size = stream_from_py.read(&mut buf)?; + assert_eq!(size, 0); + assert_eq!(buf, expect); + + Ok(()) + }) } #[test] fn test_seek() -> PyResult<()> { - let gil = Python::acquire_gil(); - let py = gil.python(); - - let locals = [("io", py.import("io")?)].into_py_dict(py); - let code = "io.BytesIO(b'a' * 100 + b'b' * 50)"; - let result = py.eval(code, None, Some(&locals))?; - let mut stream_from_py = StreamFromPy { - py_stream: result.into_py(py), - }; - - let pos = stream_from_py.seek(io::SeekFrom::Start(0))?; - assert_eq!(pos, 0); - - let pos = stream_from_py.seek(io::SeekFrom::End(0))?; - assert_eq!(pos, 150); - - let pos = stream_from_py.seek(io::SeekFrom::Start(100))?; - assert_eq!(pos, 100); - - let pos = stream_from_py.seek(io::SeekFrom::Current(0))?; - assert_eq!(pos, 100); - - let mut buf = vec![0u8; 100]; - let size = stream_from_py.read(&mut buf)?; - assert_eq!(size, 50); - let mut expect = vec![b'b'; 50]; - expect.append(&mut vec![0u8; 50]); - assert_eq!(buf, expect); - - let pos = stream_from_py.seek(io::SeekFrom::Current(0))?; - assert_eq!(pos, 150); - - Ok(()) + Python::with_gil(|py| { + let locals = [("io", py.import("io")?)].into_py_dict(py); + let code = "io.BytesIO(b'a' * 100 + b'b' * 50)"; + let result = py.eval(code, None, Some(locals))?; + let mut stream_from_py = StreamFromPy { + py_stream: result.into_py(py), + }; + + let pos = stream_from_py.seek(io::SeekFrom::Start(0))?; + assert_eq!(pos, 0); + + let pos = stream_from_py.seek(io::SeekFrom::End(0))?; + assert_eq!(pos, 150); + + let pos = stream_from_py.seek(io::SeekFrom::Start(100))?; + assert_eq!(pos, 100); + + let pos = stream_from_py.seek(io::SeekFrom::Current(0))?; + assert_eq!(pos, 100); + + let mut buf = vec![0u8; 100]; + let size = stream_from_py.read(&mut buf)?; + assert_eq!(size, 50); + let mut expect = vec![b'b'; 50]; + expect.append(&mut vec![0u8; 50]); + assert_eq!(buf, expect); + + let pos = stream_from_py.seek(io::SeekFrom::Current(0))?; + assert_eq!(pos, 150); + + Ok(()) + }) } }