Skip to content

Fixed #27150 -- Made base File objects truthy by default.#20327

Merged
sarahboyce merged 1 commit intodjango:mainfrom
VIZZARD-X:ticket-27150-doc-file-name
Apr 14, 2026
Merged

Fixed #27150 -- Made base File objects truthy by default.#20327
sarahboyce merged 1 commit intodjango:mainfrom
VIZZARD-X:ticket-27150-doc-file-name

Conversation

@VIZZARD-X
Copy link
Copy Markdown
Contributor

@VIZZARD-X VIZZARD-X commented Nov 26, 2025

Trac ticket number

ticket-27150

Branch description

Originally, this PR proposed a documentation update. However, following the consensus reached here.

The base File class previously fell back to __len__ for boolean evaluation because it lacked a __bool__ method. This caused thin wrappers around valid but nameless or empty file-like objects to unexpectedly evaluate to False.

This PR makes the base File class true by default to fix the buggy boolean evaluation of nameless file wrappers like BytesIO. It strictly preserves the existing name-based evaluation logic in FieldFile and UploadedFile to protect framework behavior, and includes a backward-incompatible release note for Django 6.1.

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.
  • I have attached screenshots in both light and dark modes for any UI changes.

@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch from 5f83965 to b6ede76 Compare November 26, 2025 08:59
@blighj
Copy link
Copy Markdown
Contributor

blighj commented Mar 24, 2026

I had a look at this ticket, and I think the docs approach is more of a bandaid, I've updated the ticket with my investigation and recommendation for a code cleanup rather than documenting the odd behaviour. I've moved the ticket to unreviewed, so a triage team member can weigh in in time.

The doc change you came up with in itself is good, but I think a more thorogh approach is better. If the triagers do agree that a code change is the right approach feel free to be the one to submit that PR if you are still interested.

@blighj
Copy link
Copy Markdown
Contributor

blighj commented Mar 26, 2026

That ticket has been triaged now based on the investigation, if you pick it back up I'll rereview

@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch 2 times, most recently from 07c12a6 to fc9c9fb Compare April 2, 2026 19:38
@VIZZARD-X VIZZARD-X changed the title Fixed #27150 — Document that file-like objects without a name must supply one when wrapped by File. Fixed #27150 — Fixed boolean evaluation of base File objects without a name. Apr 2, 2026
@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch from fc9c9fb to f83ed76 Compare April 2, 2026 20:09
@VIZZARD-X
Copy link
Copy Markdown
Contributor Author

Many thanks to James for taking a deep dive into this, and to Jacob for his thoughtful insights as always. The PR is ready for another review, please let me know if any changes are needed 👍

Comment thread docs/releases/6.1.txt Outdated
@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch from f83ed76 to 54608c5 Compare April 2, 2026 21:01
Comment thread docs/releases/6.1.txt Outdated
Comment on lines +477 to +478
File uploads/storage
--------------------
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert in this area, but I've had a look at previous release note docs, and I don't see headings introduced like this very often. Far more typical to see it in the Miscellaneous section below. I think I'd put it there, but at this stage you are more experience contributor to django than me. So just my 2 cents.

Copy link
Copy Markdown
Contributor Author

@VIZZARD-X VIZZARD-X Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I think it's the right thing to do, having an entire dedicated subheading for a single point doesn't make much sense. Also since it's a really old ticket adding it to miscellaneous would be better since most users wouldn't be affected by this change, given that it's coming from Django 1.10.

@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch from 54608c5 to e0200c1 Compare April 2, 2026 21:48
Copy link
Copy Markdown
Contributor

@blighj blighj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is as good as my reviews can make it now. The final wording may well get changed slightly by a merger, but anything I might suggest is as likely to be changed.

Copy link
Copy Markdown
Contributor

@sarahboyce sarahboyce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the work and reviews on this ticket 💜

As we have a test class files.tests.NoNameFileTestCase, I was wondering if we would like to add a few explicit test cases such as:

--- a/tests/files/tests.py
+++ b/tests/files/tests.py
@@ -233,6 +233,15 @@ class NoNameFileTestCase(unittest.TestCase):
     def test_noname_file_get_size(self):
         self.assertEqual(File(BytesIO(b"A file with no name")).size, 19)
 
+    def test_noname_bool(self):
+        self.assertTrue(bool(File(BytesIO(b"A file with no name"))))
+
+    def test_noname_repr(self):
+        self.assertEqual(repr(File(BytesIO(b"A file with no name"))), "<File: None>")
+
+    def test_noname_bool_uploaded(self):
+        self.assertFalse(bool(UploadedFile(file=BytesIO(b"A file with no name"))))
+
 
 class ContentFileTestCase(unittest.TestCase):

What do we think? Perhaps just the test test_noname_bool adds the behavior change explicitly to the test suite?

Comment thread docs/releases/6.1.txt Outdated
Comment on lines +498 to +502
* The base :class:`~django.core.files.File` class now evaluates to
``True`` by default, rather than relying on the file's ``name`` attribute.
Subclasses like :class:`~django.db.models.fields.files.FieldFile` and
:class:`~django.core.files.uploadedfile.UploadedFile` retain their
previous behavior of evaluating based on this attribute.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only suggestion here is perhaps "Subclasses like" needs to be more precise as not all subclasses retain the previous behavior (such as ContentFile). This also doesn't currently list all built-in subclasses which retain the previous behavior. Maybe:

Suggested change
* The base :class:`~django.core.files.File` class now evaluates to
``True`` by default, rather than relying on the file's ``name`` attribute.
Subclasses like :class:`~django.db.models.fields.files.FieldFile` and
:class:`~django.core.files.uploadedfile.UploadedFile` retain their
previous behavior of evaluating based on this attribute.
* The :class:`~django.core.files.File` class now always evaluates to ``True``
in boolean contexts, rather than relying on the ``name`` attribute. The
built-in subclasses ``FieldFile``, ``UploadedFile``,
``TemporaryUploadedFile``, ``InMemoryUploadedFile``, and
``SimpleUploadedFile`` retain the previous behavior of evaluating based on
the ``name`` attribute.

@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch from e0200c1 to 8b67987 Compare April 10, 2026 14:46
@VIZZARD-X VIZZARD-X force-pushed the ticket-27150-doc-file-name branch from 8b67987 to 90786db Compare April 10, 2026 14:48
Copy link
Copy Markdown
Contributor

@blighj blighj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those changes look good. Adding just the one extra suggested test, test_noname_bool seems fair and the wording proposed by Sarah is added and reads well.

@sarahboyce sarahboyce changed the title Fixed #27150 — Fixed boolean evaluation of base File objects without a name. Fixed #27150 -- Made base File objects truthy by default. Apr 13, 2026
Copy link
Copy Markdown
Contributor

@sarahboyce sarahboyce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@sarahboyce sarahboyce merged commit 3157285 into django:main Apr 14, 2026
45 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants