Opened 9 years ago
Last modified 9 years ago
#27150 new Cleanup/optimization
Document that a name should be provided when wrapping file-like objects that don't have one with File
| Reported by: | Sergei Zh | Owned by: | nobody |
|---|---|---|---|
| Component: | Documentation | Version: | 1.10 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
django.core.files.base.File supports file-like objects (synonym to file object in python glossary) and in fact can't rely on additional name attribute, but in current implementation of __bool__ method it does:
def __bool__(self):
return bool(self.name)
For example, until tempfile.SpooledTemporaryFile isn't large enough to have been written to disk, his name attribute is None and if statement will return False.
import tempfile
from django.core.files.base import File
python_file_like_object = tempfile.SpooledTemporaryFile()
file_obj = File(python_file_like_object) # name keyword is None by default
if file_object: # Falsy, because python_file_like_object.name is None
print("42")
The same behavior with streams (BytesIO, StringIO).
Maybe __bool__ method should rely on self.file attribute to avoid this behavior?
Change History (7)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
Hi.
Sure, it makes sense. I'll try to investigate failed tests ASAP. Think it's the best place to begin.
comment:3 by , 9 years ago
| Component: | Core (Other) → Documentation |
|---|---|
| Summary: | Wrong File object behavior if file object has no name attribute → Document that a name should be provided when wrapping file-like objects that don't have one with File |
| Triage Stage: | Unreviewed → Accepted |
| Type: | Bug → Cleanup/optimization |
See #26495 for a case where this came up. Unless investigation yields otherwise, I think documenting that you should pass a name for file-like objects that don't have one is the best course of action. I'm not sure if raising an error for that case might be acceptable (there might be use cases where providing name isn't needed) but if so, they would likely be even more helpful.
comment:4 by , 9 years ago
As I understood from #26495 python file-like objects works fine with requests library, because in CPython file objects use object.__bool__ and always returns True if no __bool__ and __len__.
I think documenting that you should pass a name for file-like objects that don't have one is the best course of action.
It's little bit strange for me to allow pass name=None to Storage.save, while disallow use empty name for file-like objects. Maybe we can restore default __bool__ behavior in Storage.save method?
content.__bool__ = lambda _: True
comment:5 by , 9 years ago
I've realized it's wrong, we should delete __bool__ method, cause default implementation depends on __len__ method.
comment:6 by , 9 years ago
I haven't looked into the issue so I can't propose an alternative, however, I'm not sure that patching methods like that is a good practice. At least, I'm not aware of anywhere else in Django that uses that pattern.
Hi,
As far as I can tell,
File.__bool__is not documented but it does seem to be used internally and is somewhat tested (though maybe not directly): changing it toreturn Falseyields quite a few errors and failures in the test suite.Because of this lack of documentation, it's hard to tell if the behavior you're describing is a bug.
I think it'd be worth it to:
1) Document
File.__bool__(both in the reference docs and in the docstring)2) Figure out if we can improve it by handling underlying files with no names as you suggest.
What do you think?