Skip to content

A small helper library for working with python file-like objects with rust.

Notifications You must be signed in to change notification settings

omerbenamram/pyo3-file

Folders and files

NameName
Last commit message
Last commit date

Latest commit

6c677dd · Apr 1, 2025
Jun 24, 2023
Feb 18, 2023
Apr 1, 2025
Apr 1, 2025
Jun 11, 2024
Apr 1, 2025
Aug 27, 2024
Apr 1, 2025
Apr 1, 2025
May 20, 2019
Jun 28, 2020

Repository files navigation

crates.io

PyO3-File

This is a small utility library to facilitate working with python file-like objects with rust.

Example

An example use case for this is when a file is opened in python, and needs to be passed to a rust library.

We could support both by introspecting the PyObject, and pick the correct behavior.

We would like this to work:

from path_or_file_like import accepts_path_or_file_like

def main():
    # should open `some_file.txt`.
    accepts_path_or_file_like("./some_file.txt")

    # should read from the python handle.
    f = open('./some_file.txt')
    accepts_path_or_file_like(f)

We could use pyo3_file to extend an existing a pyo3 module.

use pyo3_file::PyFileLikeObject;
use pyo3::types::PyString;

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use std::io::Read;
use std::fs::File;

/// Represents either a path `File` or a file-like object `FileLike`
#[derive(Debug)]
enum FileOrFileLike {
    File(String),
    FileLike(PyFileLikeObject),
}

impl<'py> FromPyObject<'py> for FileOrFileLike {
    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
        // is a path
        if let Ok(string) = ob.extract::<String>() {
            return Ok(FileOrFileLike::File(string));
        }

        // is a file-like
        let f = PyFileLikeObject::py_with_requirements(ob.clone(), true, false, true, false)?;
        Ok(FileOrFileLike::FileLike(f))
    }
}

#[pyfunction]
/// Opens a file or file-like, and reads it to string.
fn accepts_path_or_file_like(path_or_file_like: FileOrFileLike) -> PyResult<String> {
    match path_or_file_like {
        FileOrFileLike::File(s) => {
            println!("It's a file! - path {}", s);
            let mut f = File::open(s)?;
            let mut string = String::new();

            f.read_to_string(&mut string)?;
            Ok(string)
        }
        FileOrFileLike::FileLike(mut f) => {
            println!("Its a file-like object");
            let mut string = String::new();

            f.read_to_string(&mut string)?;
            Ok(string)
        }
    }
}

#[pymodule]
fn path_or_file_like(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(accepts_path_or_file_like))?;

    Ok(())
}


# fn main() {}

About

A small helper library for working with python file-like objects with rust.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages