#19905 closed Bug (fixed)
ResourceWarning in formtools tests
Reported by: | Florian Apolloner | Owned by: | nobody |
---|---|---|---|
Component: | contrib.formtools | Version: | dev |
Severity: | Release blocker | Keywords: | |
Cc: | bmispelon@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
running formtools tests with
PYTHONPATH=.. python3.3 -Wall ./runtests.py --settings=test_sqlite --verbosity=2 formtools
yields
/usr/lib/python3.3/unittest/case.py:385: ResourceWarning: unclosed file <_io.BufferedReader name='/tmp/django_512q8m/tmpjkx__v/tests_6.py'> function()
quite often. I couldn't yet determine if that's a bug in the wizard code or our tests.
Attachments (1)
Change History (17)
comment:1 by , 12 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 12 years ago
comment:3 by , 12 years ago
Cc: | added |
---|
comment:4 by , 12 years ago
I've made a bit of progress on my branch: https://github.com/bmispelon/django/compare/ticket-19905
Moving the opening/closing of files to setUp/tearDown, I managed to reduce the number of ResourceWarning from 26 to 20.
The command I use for counting the warnings is the following: PYTHONPATH=.. python3 -Wall ./runtests.py --settings=test_sqlite --verbosity=2 formtools 2>&1 | grep ResourceWarning | wc -l
(from django/tests
).
comment:5 by , 12 years ago
I made a test using io.BytesIO
instead of opening actual files and the number or warnings doesn't change.
This seems like a pretty conclusive evidence that the problem lies with formtools' code itself rather than the tests.
Here's the list of the methods that leak file descriptors:
NamedWizardTests.test_form_finish
: 2NamedWizardTests.test_cleaned_data
: 3WizardTests.test_form_finish
: 2WizardTests.test_cleaned_data
: 3WizardTests.test_form_reresh
: 3
As each class is ran twice (once for session and once for cookie-based wizard), that amounts to 26 leaked descriptors.
comment:6 by , 11 years ago
For what it's worth, I wasn't able to duplicate these ResourceWarnings
(in Python 2.7.5 and 3.3.2 under Windows).
Taking a quick glance at the code, the only thing that jumps out at me is that formtools.wizard.storage.base.BaseStorage.get_step_files()
opens temp files that get passed along (via current_step_files
). I don't know enough about this code to say when or whether these file handles get closed, but I thought I'd mention it.
comment:7 by , 11 years ago
Basically, the explanation of this behavior is rather straightforward: at various steps, formtools is reopening files (in get_step_files
) to provide them to the wizard form(s), a bit like a standard UploadHandler
does it for data coming from a request to populate request.FILES
(and then form files data).
If we look at the same process with standard forms, we can see that we don't explicitly close the files either (not an issue with InMemoryUploadedFile
, not sure about TemporaryUploadedFile
for bigger files). In standard form tests, it's easy to manually close files as we are opening them ourselves. It's different in formtools tests, as those files are reopened inside formtools code.
This leaves us with two paths:
- We don't think that not explicitly closing files in this situation is a problem, and we should then simply silence the warnings (didn't try if it's possible or not) or live with them.
- We do think that open files provided to forms with file fields should be explicitly closed at some point in the code (and not artifically in test code). But then the resolution is not in formtools, but in the form infrastructure itself.
I have doubts that 2 is feasible, so I'm afraid we are left with 1.
comment:8 by , 11 years ago
Has patch: | set |
---|
The attached patch is suppressing the warnings, but it's a test-only solution, that is the warnings will probably still be emitted in real user code.
comment:10 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:12 by , 11 years ago
Resolution: | fixed |
---|---|
Status: | closed → new |
Reopening, as the fix is causing failures. On Python 2 at least, __file__
can have the .pyc extension, so UPLOADED_FILE_NAME
is not always equal to __file__
. I guess the CI server is cleaning .pyc files before each run.
comment:13 by , 11 years ago
Has patch: | unset |
---|---|
Severity: | Normal → Release blocker |
Yes, CI does git clean -fqdx
before each run.
comment:14 by , 11 years ago
timo: Why did you mark this as a release blocker? We've clearly done releases containing it before...
comment:15 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
I took a peek at the tests and I'm left a bit puzzled.
The name of the unclosed files is consistent with what happens in the test (lots of
open(__file__)
).However, I don't really understand the flow of the code: it seems some files are closed before being re-opened (https://github.com/django/django/blob/master/django/contrib/formtools/tests/wizard/namedwizardtests/tests.py#L125-L126).
I found commit 64a3c7f9aeda347a72e3f1e8e88381b5b3d479d8 which seems like an attempt to fix those issues (though the commit message is not very optimistic).
I also found a line in
formtools.wizard.storage.base.BaseStorage.get_step_files()
which is a bit suspicious: https://github.com/django/django/blob/master/django/contrib/formtools/wizard/storage/base.py#L81 but I'm not familiar enough with formtools' code to tell whether that opened file gets closed later on.