[Django] #28823: Nested @override_settings on class and method do not work correctly

6 views
Skip to first unread message

Django

unread,
Nov 21, 2017, 1:58:07 AM11/21/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-----------------------------------------+------------------------
Reporter: Paolo D'Apice | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: 1.10
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+------------------------
I am using the `@override_settings~ decorator to delete some settings
during tests (accordint to the
[https://docs.djangoproject.com/en/1.10/topics/testing/tools/#overriding-
settings documentation]).

I reproduced the problem with the following code:
{{{#!python
from django.test import TestCase, override_settings
from django.conf import settings

TEST_SETTINGS = {
'MY_DATA': {
'foo': 1,
'bar': 2
}
}


class Dummy:
def foo(self):
return settings.MY_DATA.get('foo')

def bar(self):
return settings.MY_DATA.get('bar')


@override_settings(**TEST_SETTINGS)
class SimpleTest(TestCase):
def setUp(self):
self.dummy = Dummy()

def test_foobar(self):
self.assertEqual(self.dummy.foo(), 1)
self.assertEqual(self.dummy.bar(), 2)

@override_settings()
def test_delete_my_data(self):
del settings.MY_DATA
with self.assertRaises(AttributeError):
self.dummy.foo()
with self.assertRaises(AttributeError):
self.dummy.bar()

@override_settings()
def test_delete_foo(self):
del settings.MY_DATA['foo']
self.assertIsNone(self.dummy.foo())
self.assertEqual(self.dummy.bar(), 2)

def test_foobar_again(self):
self.assertEqual(self.dummy.foo(), 1)
self.assertEqual(self.dummy.bar(), 2)
}}}

I expect all the test to pass, but instead I have some failures:

{{{
..FF
======================================================================
FAIL: test_foobar (api.tests.test_bug.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/paolo/testproject/api/tests/test_bug.py", line 26, in
test_foobar
self.assertEqual(self.dummy.foo(), 1)
AssertionError: None != 1

======================================================================
FAIL: test_foobar_again (api.tests.test_bug.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/paolo/testproject/api/tests/test_bug.py", line 44, in
test_foobar_again
self.assertEqual(self.dummy.foo(), 1)
AssertionError: None != 1

----------------------------------------------------------------------
Ran 4 tests in 0.045s

FAILED (failures=2)
}}}

It seems to me that the overridden settings at method level are not
cleared up after the test method runs, leaving the settings in a ''dirty''
state.

--
Ticket URL: <https://code.djangoproject.com/ticket/28823>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Nov 21, 2017, 1:58:48 AM11/21/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+--------------------------------------

Reporter: Paolo D'Apice | Owner: nobody
Type: Bug | Status: new
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by Paolo D'Apice):

* Attachment "test_bug.py" added.

Sample test case

Django

unread,
Nov 21, 2017, 5:21:25 PM11/21/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+-------------------------------------------
Reporter: Paolo D'Apice | Owner: Stanislav Filin
Type: Bug | Status: assigned
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+-------------------------------------------
Changes (by Stanislav Filin):

* status: new => assigned
* cc: Stanislav Filin (added)
* owner: nobody => Stanislav Filin


Comment:

Good evening, it's problem not only for Django 1.10.

--
Ticket URL: <https://code.djangoproject.com/ticket/28823#comment:1>

Django

unread,
Nov 21, 2017, 6:41:38 PM11/21/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+--------------------------------------
Reporter: Paolo D'Apice | Owner: (none)

Type: Bug | Status: new
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by Stanislav Filin):

* status: assigned => new
* owner: Stanislav Filin => (none)


--
Ticket URL: <https://code.djangoproject.com/ticket/28823#comment:2>

Django

unread,
Nov 23, 2017, 3:28:35 PM11/23/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+--------------------------------------
Reporter: Paolo D'Apice | Owner: (none)

Type: Bug | Status: new
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution:

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Piotr Domański):

Is it really bad behaviour? In test_delete_foo you don't change value of
MY_DATA but you modify item in previous value of MY_DATA setting.
Rollback will be performed if you change
{{{
del settings.MY_DATA['foo']
}}}
into:
{{{
settings.MY_DATA = {'bar': 2}
}}}


Should all deep copies of all settings values be freezed during entering
override_settings? What about complex objects?

--
Ticket URL: <https://code.djangoproject.com/ticket/28823#comment:3>

Django

unread,
Nov 23, 2017, 9:32:25 PM11/23/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+--------------------------------------
Reporter: Paolo D'Apice | Owner: (none)
Type: Bug | Status: closed
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution: wontfix

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by Simon Charette):

* status: new => closed
* resolution: => wontfix


Comment:

I agree with Piotr's reasoning. We aren't deep copying mutable settings on
override and I don't think we should be.

If you want to alter mutable settings I'd suggest you override the setting
itself in the context of your alteration. In your case that would be using
decorating your `test_delete_foo` method with
`override_settings(**deepcopy(TEST_SETTINGS))`.

--
Ticket URL: <https://code.djangoproject.com/ticket/28823#comment:4>

Django

unread,
Nov 23, 2017, 10:39:56 PM11/23/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+--------------------------------------
Reporter: Paolo D'Apice | Owner: (none)
Type: Bug | Status: closed
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution: wontfix

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Paolo D'Apice):

Thanks for the explanation Simon. I believe it is reasonable to update the
documentation as well, especially where it says:

You can also simulate the absence of a setting by deleting it after
settings have been overridden, like this:
{{{#!python
@override_settings()
def test_something(self):
del settings.LOGIN_URL
...
}}}

because that does not work as expected.

--
Ticket URL: <https://code.djangoproject.com/ticket/28823#comment:5>

Django

unread,
Nov 23, 2017, 10:57:57 PM11/23/17
to django-...@googlegroups.com
#28823: Nested @override_settings on class and method do not work correctly
-------------------------------+--------------------------------------
Reporter: Paolo D'Apice | Owner: (none)
Type: Bug | Status: closed
Component: Uncategorized | Version: 1.10
Severity: Normal | Resolution: wontfix

Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------

Comment (by Simon Charette):

Paolo, from my understanding top level setting deletion works just fine as
documented. Try commenting your

The issue you are experiencing here is that you are mutating a dict by
deleting a key from your top level `MY_DATA` setting value which isn't
documented to be working.

--
Ticket URL: <https://code.djangoproject.com/ticket/28823#comment:6>

Reply all
Reply to author
Forward
0 new messages