#29226: @modify_settings append/remove/prepend is affected by dictionary order
-------------------------------------+-------------------------------------
Reporter: Manuel | Owner: nobody
Kaufmann |
Type: | Status: new
Uncategorized |
Component: Testing | Version: 2.0
framework | Keywords: tests,
Severity: Normal | modify_settings
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I found a weird behaviour when using `@modify_settings` with `append` and
`remove` at the same time for the same elements. I used this because I
needed to modify the order of the MIDDLEWARES classes: inject a middleware
before one that it's already defined in that seeing. To do that, it's
needed to remove all the middleware after that one (including it) and the
re-add them by prepending your own.
Example:
{{{
# Original settings
MIDDLEWARES = [
'1',
'2',
'3',
'4',
'5',
]
}}}
and I need this:
{{{
# Expected settings
MIDDLEWARES = [
'1',
'2',
'3',
'MyOwnMiddlewareHere',
'4',
'5',
]
}}}
I would use `@modify_settings` in this way:
{{{
@modify_settings(MIDDLEWARES={
'append': [
'MyOwnMiddlewareHere',
'4',
'5',
],
'remove': [
'4',
'5',
],
})
class FooBarTest(TestCase):
....
}}}
This cause different behaviours depending on the Python version we are
using:
* Python < 3.6 this will randmly works since it could
- first remove and then append the items: this will produce the
expected result
- first append and then remove the items: this won't produce the
expected result
* Python >= 3.6 this will always produce the enexpected result because 3.6
has "insertion ordering" and append will be applied first all the times
- we can change this behaviour in 3.6 by putting the remove key first,
and it will always produce the expected result.
NOTE: other Python implementation (not CPython) will also experiment this
problem depending on their implementation.
I fixed this in my own code by using `collections.OrderedDict` but I think
this should be at least mentioned in the documentation to avoid other
people having this issue. Otherwise, it could require an OrderedDict.
I wrote some tests that I'm attaching the patch with some comments and
explanations on why this is happening. I'm running the tests like this:
`tox -e py35,py36 -- tests.settings_tests.tests`
NOTE: this affects multiple versions of Django
--
Ticket URL: <https://code.djangoproject.com/ticket/29226>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/050.07391979b03bbc93dae8711bd0c0ba48%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.