Code

Opened 14 months ago

Last modified 4 months ago

#19905 new Bug

ResourceWarning in formtools tests

Reported by: apollo13 Owned by: nobody
Component: contrib.formtools Version: master
Severity: Normal Keywords:
Cc: bmispelon@… Triage Stage: Accepted
Has patch: yes 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)

19905-1.diff (5.2 KB) - added by claudep 4 months ago.
Fixing test warnings

Download all attachments as: .zip

Change History (9)

comment:1 Changed 14 months ago by aaugustin

  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 13 months ago by bmispelon

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.

comment:3 Changed 13 months ago by bmispelon

  • Cc bmispelon@… added

comment:4 Changed 13 months ago by bmispelon

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).

edit: No I didn't, i just made two tests fail because of a NameError, which I didn't catch because i was just grepping the results.

Oh well, back to the drawing board. Sorry for the noise.

I did learn that NamedWizardTests causes 5 ResourceWarning every time it's run (2 for test_form_finish and 3 for test_cleaned_data) so there's that.

Last edited 13 months ago by bmispelon (previous) (diff)

comment:5 Changed 13 months ago by bmispelon

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: 2
  • NamedWizardTests.test_cleaned_data: 3
  • WizardTests.test_form_finish: 2
  • WizardTests.test_cleaned_data: 3
  • WizardTests.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 Changed 7 months ago by marfire

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 Changed 4 months ago by claudep

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:

  1. 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.
  2. 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.

Changed 4 months ago by claudep

Fixing test warnings

comment:8 Changed 4 months ago by claudep

  • 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.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as new
The owner will be changed from nobody to anonymous. Next status will be 'assigned'
as The resolution will be set. Next status will be 'closed'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.