Repository: pola-rs/polars
File: crates/polars-python/src/file.rs (Rust)

Code before:
            } else if expects_str {
                // tracks the number of chars written
                self.inner.call_method(
                    py,
                    "write",
                    (PyString::new(
                        py,
                        std::str::from_utf8(buf).map_err(io::Error::other)?,
                    ),),
                    None,
                )
            } else {
                // tracks the number of bytes written
                self.inner
                    .call_method(py, "write", (PyBytes::new(py, buf),), None)
            }
            .map_err(pyerr_to_io_err)?;

            let n = char_or_bytes_written.extract(py).map_err(pyerr_to_io_err)?;
            let n_bytes = if expects_str && !expects_str_and_is_ascii {
                // substitute char count with buf len
                let expected_chars = std::str::from_utf8(buf)
                    .map_err(io::Error::other)?
                    .chars()
                    .count();
                assert!(n == expected_chars);
                buf_len
            } else {
                n
            };
            Ok(n_bytes)
        })
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        if self.has_flush {
            Python::with_gil(|py| {
                self.inner
                    .call_method(py, "flush", (), None)
                    .map_err(pyerr_to_io_err)
            })?;
        }

        Ok(())
    }
}

impl Seek for PyFileLikeObject {
    fn seek(&mut self, pos: SeekFrom) -> Result<u64, io::Error> {
        Python::with_gil(|py| {
            let (whence, offset) = match pos {

Review comment (bug):
I think this is not what you want. You want to do is find the offset of the nth char. This would go wrong if you have a rate limited network interface for instance. You can use `.char_indices().nth(n).map(|(i, _)| i).expect("...")` for this.

```


Code after:
                number_chars_written.extract(py).map_err(pyerr_to_io_err)?
            } else if expects_str {
                let number_chars_written = self
                    .inner
                    .call_method(
                        py,
                        "write",
                        (PyString::new(
                            py,
                            std::str::from_utf8(buf).map_err(io::Error::other)?,
                        ),),
                        None,
                    )
                    .map_err(pyerr_to_io_err)?;
                let n_chars: usize = number_chars_written.extract(py).map_err(pyerr_to_io_err)?;
                // calculate n_bytes
                if n_chars > 0 {
                    std::str::from_utf8(buf)
                        .map(|str| {
                            str.char_indices()
                                .nth(n_chars - 1)
                                .map(|(i, ch)| i + ch.len_utf8())
                                .unwrap()
                        })
                        .expect("unable to parse buffer as utf-8")
                } else {
                    0
                }
            } else {
                let number_bytes_written = self
                    .inner
                    .call_method(py, "write", (PyBytes::new(py, buf),), None)
                    .map_err(pyerr_to_io_err)?;
                number_bytes_written.extract(py).map_err(pyerr_to_io_err)?
            };
            Ok(n_bytes)
        })
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        if self.has_flush {
            Python::with_gil(|py| {
                self.inner
                    .call_method(py, "flush", (), None)
                    .map_err(pyerr_to_io_err)
            })?;
        }

        Ok(())
    }
}