jazzband / jazzband/tablib

Different file formats require user to know if file should be opened binary or not

Open
#511 2 comments 3 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
4.8k
Forks
617
PR merge metrics
No merged PRs in 30d

Description

From the docs, I think this is working as designed, but wanted to check. There's a decent chance I'm doing something wrong.

File auto-detection becomes less useful to library consumer like me if I have to check the type of file I'm using and take different branches for it. It's still great to get a normalized representation of various formats . . . thanks for that.

If you open an Excel file (.xlsx) with just mode `r`, you get an error `zipfile.BadZipFile: File is not a zip file`. Doesn't matter if I specify the format in the second parameter to `load()` when calling `open()` myself. You must specify mode `rb`.

This in on Ubuntu 20.04, python3.9, openpyxl 3.0.9

```python
# zipfile.BadZipFile: File is not a zip file
with open("mySheet.xlsx", "r") as fh:
data.load(fh)

# OK
with open("mySheet.xlsx", "rb") as fh:
data.load(fh)
```
If you pass the file path, it cannot determine the file type. If you specify the type, it doesn't open binary.
```python
# zipfile.BadZipFile: File is not a zip file
data.load("mySheet.xlsx", "xlsx")

# tablib.exceptions.UnsupportedFormat: Tablib has no format 'None' or it is not registered.
data.load("mySheet.xlsx")
```
I think the issue in `data.load("mySheet.xlsx", "xlsx")` is because `core.normalize_input()` converts the path given as a str to a StringIO. And when openpyxl passes it to zipfile, zipfile would call `open()` with mode `rb` if it was still a string. I'm not sure zipfile is ready for StringIO at all. It hits this code block which doesn't seem to expect a StringIO: https://github.com/python/cpython/blob/main/Lib/zipfile.py#L1273

Now if I shift to CSV, I can't use mode `rb`. It does give instructions in the exception if you give it the file type hint. And it does get it right if you leave the call to `open()` to tablib and give it the format hint.

```python
# tablib.exceptions.UnsupportedFormat: Tablib has no format 'None' or it is not registered.
with open("myCsv.csv", "rb") as fh:
data.load(fh)

# _csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)
with open("myCsv.csv", "rb") as fh:
data.load(fh, "csv")

# tablib.exceptions.UnsupportedFormat: Tablib has no format 'None' or it is not registered.
data.load("myCsv.csv")

# OK
data.load("myCsv.csv", "csv")
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.