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

requests.utils.super_len() can't cope with tarfile members #5229

Closed
dimbleby opened this issue Oct 16, 2019 · 3 comments · Fixed by #5239
Closed

requests.utils.super_len() can't cope with tarfile members #5229

dimbleby opened this issue Oct 16, 2019 · 3 comments · Fixed by #5239

Comments

@dimbleby
Copy link
Contributor

dimbleby commented Oct 16, 2019

Expected Result

POSTing a large file that I have extracted from a tarfile. I expect that requests should be able to determine the length of that file, set the Content-Length header, and upload it efficiently.

Actual Result

requests fails to determine the file length, goes with Transfer-Encoding: chunked, and the upload is much slower than desired.

Reproduction Steps

Start with a small tarfile, say

echo foo > file1
tar cf tarfile.tar file1

Then use requests.utils.super_len to try and get the length of file1 in the tarfile:

#!/usr/bin/env python
import tarfile
import requests

tar = tarfile.open("tarfile.tar")
member = tar.extractfile("file1")
print(f"super_length of member is {requests.utils.super_len(member)}")

result:

Traceback (most recent call last):
  File "./demo.py", line 7, in <module>
    print(f"super_length of member is {requests.utils.super_len(member)}")
  File "/data/developer/.virtualenvs/req-tar/lib/python3.6/site-packages/requests/utils.py", line 119, in super_len
    fileno = o.fileno()
AttributeError: '_FileInFile' object has no attribute 'fileno'

The behavior of the member is quite strange here: hasattr(member, fileno) is true, but trying to call member.fileno() results in an AttributeError.

I expect that a sensible fix might be for this exception to catch a broader range of errors.

One can get the length of the member by seeking, so I expect that super_len() should then succeed.

System Information

$ python -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "2.8"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.8"
  },
  "platform": {
    "release": "3.10.0-1062.1.1.el7.x86_64",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.22.0"
  },
  "system_ssl": {
    "version": "100020bf"
  },
  "urllib3": {
    "version": "1.25.6"
  },
  "using_pyopenssl": false
}
@tirkarthi
Copy link

I feel it should be raising unsupported exception when the underlying attribute doesn't have fileno. I have opened https://bugs.python.org/issue38572

@dimbleby
Copy link
Contributor Author

Sounds reasonable, thanks - though obviously I hope that meanwhile we can get a workaround/fix here, per #5239.

@nateprewitt
Copy link
Member

Resolved with #5239

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 26, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants