Skip to content

Commit

Permalink
Merge pull request #13 from jelmer/asrawfd
Browse files Browse the repository at this point in the history
Implement AsRawFd for PyFileLikeObject
  • Loading branch information
omerbenamram authored Nov 27, 2023
2 parents 14e8f5f + 2abeb12 commit d2085e4
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl FileOrFileLike {
}

// is a file-like
match PyFileLikeObject::with_requirements(path_or_file_like, true, false, true) {
match PyFileLikeObject::with_requirements(path_or_file_like, true, false, true, false) {
Ok(f) => Ok(FileOrFileLike::FileLike(f)),
Err(e) => Err(e)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/path_or_file_like/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl FileOrFileLike {
}

// is a file-like
match PyFileLikeObject::with_requirements(path_or_file_like, true, false, true) {
match PyFileLikeObject::with_requirements(path_or_file_like, true, false, true, false) {
Ok(f) => Ok(FileOrFileLike::FileLike(f)),
Err(e) => Err(e),
}
Expand Down Expand Up @@ -61,7 +61,7 @@ fn accepts_path_or_file_like_read(path_or_file_like: PyObject) -> PyResult<Strin
/// Opens a file or file-like, and write a string to it.
fn accepts_file_like_write(file_like: PyObject) -> PyResult<()> {
// is a file-like
match PyFileLikeObject::with_requirements(file_like, false, true, false) {
match PyFileLikeObject::with_requirements(file_like, false, true, false, false) {
Ok(mut f) => {
println!("Its a file-like object");
f.write_all(b"Hello, world!")?;
Expand Down
27 changes: 26 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use pyo3::types::{PyBytes, PyString, PyType};

use std::io;
use std::io::{Read, Seek, SeekFrom, Write};
use std::os::fd::{AsRawFd, RawFd};

#[derive(Debug)]
pub struct PyFileLikeObject {
Expand Down Expand Up @@ -33,12 +34,13 @@ impl PyFileLikeObject {

/// Same as `PyFileLikeObject::new`, but validates that the underlying
/// python object has a `read`, `write`, and `seek` methods in respect to parameters.
/// Will return a `TypeError` if object does not have `read`, `seek`, and `write` methods.
/// Will return a `TypeError` if object does not have `read`, `seek`, `write` and `fileno` methods.
pub fn with_requirements(
object: PyObject,
read: bool,
write: bool,
seek: bool,
fileno: bool,
) -> PyResult<Self> {
Python::with_gil(|py| {
if read && object.getattr(py, "read").is_err() {
Expand All @@ -59,6 +61,12 @@ impl PyFileLikeObject {
));
}

if fileno && object.getattr(py, "fileno").is_err() {
return Err(PyErr::new::<PyTypeError, _>(
"Object does not have a .fileno() method.",
));
}

PyFileLikeObject::new(object)
})
}
Expand Down Expand Up @@ -179,3 +187,20 @@ impl Seek for PyFileLikeObject {
})
}
}

impl AsRawFd for PyFileLikeObject {
fn as_raw_fd(&self) -> RawFd {
Python::with_gil(|py| {
let fileno = self
.inner
.getattr(py, "fileno")
.expect("Object does not have a fileno() method.");

let fd = fileno
.call(py, (), None)
.expect("fileno() method did not return a file descriptor.");

fd.extract(py).expect("File descriptor is not an integer.")
})
}
}

0 comments on commit d2085e4

Please sign in to comment.