Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(python): truncate file path on error msg #6917

Merged
merged 1 commit into from
Feb 16, 2023
Merged
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
34 changes: 21 additions & 13 deletions py-polars/src/file.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// Credits to https://github.com/omerbenamram/pyo3-file
use std::borrow::Borrow;
use std::fs::File;
use std::io;
use std::io::{BufReader, Cursor, Read, Seek, SeekFrom, Write};
Expand Down Expand Up @@ -191,23 +189,34 @@ pub enum EitherRustPythonFile {
Rust(BufReader<File>),
}

fn no_such_file_err(file_path: &str) -> PyResult<()> {
let msg = if file_path.len() > 88 {
let file_path: String = file_path.chars().rev().take(88).collect();
format!("No such file or directory: ...{file_path}",)
} else {
format!("No such file or directory: {file_path}",)
};

Err(PyErr::new::<PyFileNotFoundError, _>(msg))
}

///
/// # Arguments
/// * `truncate` - open or create a new file.
pub fn get_either_file(py_f: PyObject, truncate: bool) -> PyResult<EitherRustPythonFile> {
Python::with_gil(|py| {
if let Ok(pstring) = py_f.downcast::<PyString>(py) {
let rstring = pstring.to_string();
let str_slice: &str = rstring.borrow();
let s = pstring.to_str()?;
let file_path = std::path::Path::new(&s);
let file_path = resolve_homedir(file_path);
let f = if truncate {
BufReader::new(File::create(str_slice)?)
BufReader::new(File::create(file_path)?)
} else {
match File::open(str_slice) {
match File::open(&file_path) {
Ok(file) => BufReader::new(file),
Err(_e) => {
return Err(PyErr::new::<PyFileNotFoundError, _>(format!(
"No such file or directory: {str_slice}",
)))
no_such_file_err(s)?;
unreachable!();
}
}
};
Expand All @@ -234,15 +243,14 @@ pub fn get_mmap_bytes_reader<'a>(py_f: &'a PyAny) -> PyResult<Box<dyn MmapBytesR
}
// string so read file
else if let Ok(pstring) = py_f.downcast::<PyString>() {
let s = pstring.to_string();
let s = pstring.to_str()?;
let p = std::path::Path::new(&s);
let p = resolve_homedir(p);
let f = match File::open(p) {
Ok(file) => file,
Err(_e) => {
return Err(PyErr::new::<PyFileNotFoundError, _>(format!(
"No such file or directory: {s}",
)))
no_such_file_err(s)?;
unreachable!();
}
};
Ok(Box::new(f))
Expand Down
9 changes: 9 additions & 0 deletions py-polars/tests/unit/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,3 +447,12 @@ def test_string_numeric_arithmetic_err() -> None:
pl.ComputeError, match=r"Arithmetic on string and numeric not allowed"
):
df.select(pl.col("s") + 1)


def test_file_path_truncate_err() -> None:
content = "lskdfj".join(str(i) for i in range(25))
with pytest.raises(
FileNotFoundError,
match=r"\.\.\.42jfdksl32jfdksl22jfdksl12jfdksl02jfdksl91jfdksl81jfdksl71jfdksl61jfdksl51jfdksl41jfdksl",
):
pl.read_csv(content)