From 205f67cd5bea242fac6b0380fa26570505d07dcb Mon Sep 17 00:00:00 2001 From: Allen Jonathan David Date: Sat, 1 Jan 2022 18:38:27 +0530 Subject: [PATCH] Refs #33216 -- Made @deconstructible do not change path for subclasses. --- django/utils/deconstruct.py | 6 ++++-- tests/utils_tests/test_deconstruct.py | 28 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/django/utils/deconstruct.py b/django/utils/deconstruct.py index aa952f6b73..9d073902f3 100644 --- a/django/utils/deconstruct.py +++ b/django/utils/deconstruct.py @@ -23,7 +23,7 @@ def deconstructible(*args, path=None): and keyword arguments. """ # Fallback version - if path: + if path and type(obj) is klass: module_name, _, name = path.rpartition('.') else: module_name = obj.__module__ @@ -40,7 +40,9 @@ def deconstructible(*args, path=None): "https://docs.djangoproject.com/en/%s/topics/migrations/#serializing-values" % (name, module_name, get_docs_version())) return ( - path or '%s.%s' % (obj.__class__.__module__, name), + path + if path and type(obj) is klass + else f'{obj.__class__.__module__}.{name}', obj._constructor_args[0], obj._constructor_args[1], ) diff --git a/tests/utils_tests/test_deconstruct.py b/tests/utils_tests/test_deconstruct.py index 590e9b3811..f384ab8288 100644 --- a/tests/utils_tests/test_deconstruct.py +++ b/tests/utils_tests/test_deconstruct.py @@ -19,6 +19,10 @@ class DeconstructibleWithPathClass: pass +class DeconstructibleWithPathChildClass(DeconstructibleWithPathClass): + pass + + @deconstructible( path='utils_tests.deconstructible_classes.DeconstructibleInvalidPathClass', ) @@ -26,6 +30,10 @@ class DeconstructibleInvalidPathClass: pass +class DeconstructibleInvalidPathChildClass(DeconstructibleInvalidPathClass): + pass + + class DeconstructibleTests(SimpleTestCase): def test_deconstruct(self): obj = DeconstructibleClass('arg', key='value') @@ -51,6 +59,16 @@ class DeconstructibleTests(SimpleTestCase): self.assertEqual(args, ('arg',)) self.assertEqual(kwargs, {'key': 'value'}) + def test_deconstruct_child_with_path(self): + obj = DeconstructibleWithPathChildClass('arg', key='value') + path, args, kwargs = obj.deconstruct() + self.assertEqual( + path, + 'utils_tests.test_deconstruct.DeconstructibleWithPathChildClass', + ) + self.assertEqual(args, ('arg',)) + self.assertEqual(kwargs, {'key': 'value'}) + def test_invalid_path(self): obj = DeconstructibleInvalidPathClass() docs_version = get_docs_version() @@ -66,3 +84,13 @@ class DeconstructibleTests(SimpleTestCase): ) with self.assertRaisesMessage(ValueError, msg): obj.deconstruct() + + def test_parent_invalid_path(self): + obj = DeconstructibleInvalidPathChildClass('arg', key='value') + path, args, kwargs = obj.deconstruct() + self.assertEqual( + path, + 'utils_tests.test_deconstruct.DeconstructibleInvalidPathChildClass', + ) + self.assertEqual(args, ('arg',)) + self.assertEqual(kwargs, {'key': 'value'})