#21740 closed Cleanup/optimization (fixed)
client.py uses mutable default arguments, which is bad practice
| Reported by: | sleepydragon | Owned by: | anonymous | 
|---|---|---|---|
| Component: | Testing framework | Version: | dev | 
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | yes | UI/UX: | no | 
Description
In django/test/client.py there are several methods that have data={} in their argument lists.  The {} dictionary is a mutable type and it is not recommended to use mutable objects as default arguments.  This is because each invocation of the method where data is not specified will use the same dict object.  This enables completely unrelated method calls to affect each other.
The fix that I recommend is to instead use data=None in the argument list for the affected methods and then in the method body check for None and create a new dict if it is None.  That way each method invocation gets their own, local dict object.  I have attached a patch for review.
I'm fairly new to Django so it's possible that data=None is actually a meaningful value.  If that is the case then this approach will need to be tweaked a bit.
Attachments (2)
Change History (12)
by , 12 years ago
| Attachment: | client_mutable_argument_fix_01.patch added | 
|---|
comment:1 by , 12 years ago
| Triage Stage: | Unreviewed → Accepted | 
|---|---|
| Version: | 1.6 → master | 
comment:2 by , 12 years ago
| Owner: | changed from to | 
|---|---|
| Status: | new → assigned | 
by , 12 years ago
| Attachment: | client_mutable_argument_fix_02.patch added | 
|---|
comment:4 by , 12 years ago
To make sense, a test should fail before applying the patch, which is not the case here. I'll commit an amended patch soon (without tests).
comment:5 by , 12 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | assigned → closed | 
comment:6 by , 11 years ago
| Resolution: | fixed | 
|---|---|
| Status: | closed → new | 
This fix actually changed the behavior of the test client. I have some tests about HTTP header handling, which I pass an empty string as the request content. So it is like:
self.client.post(url, '', content_type='application/json',
                                    **{
                                        'CUSTOM_HEADER': header_1,
                                    })
Before this change everything worked fine.
The request.body became "{}" after this change. That is because when data is an empty string
data or {}
returns {} instead of ""
comment:8 by , 11 years ago
| Triage Stage: | Accepted → Ready for checkin | 
|---|
@tony-zhu FYI, it's preferred to open a new ticket for new bugs after a ticket is released.
PR looks good me; it just needs release notes.
comment:9 by , 11 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | new → closed | 
It looks like the
dictcreation should be moved at theRequestFactorylevel which also suffer from the same issues.