From f92e68c30a0d38d25486e3f3cfabe5dfb5961ef7 Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Wed, 13 Sep 2023 15:49:10 +0100 Subject: [PATCH] Fixed #34822 -- Added support for serializing functions decorated with functools.lru_cache in migrations. `@functools.cache` and `@functools.lru_cache` return an object of type `functools._lru_cache_wrapper` which prevented the migrations serializer from working. Simply using the existing `FunctionTypeSerializer` for this additional type works as expected. --- django/db/migrations/serializer.py | 1 + docs/releases/5.0.txt | 4 +++- docs/topics/migrations.txt | 7 +++++++ tests/migrations/test_writer.py | 12 ++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py index 06657ebaab..69e10fd41b 100644 --- a/django/db/migrations/serializer.py +++ b/django/db/migrations/serializer.py @@ -350,6 +350,7 @@ class Serializer: types.FunctionType, types.BuiltinFunctionType, types.MethodType, + functools._lru_cache_wrapper, ): FunctionTypeSerializer, collections.abc.Iterable: IterableSerializer, (COMPILED_REGEX_TYPE, RegexObject): RegexSerializer, diff --git a/docs/releases/5.0.txt b/docs/releases/5.0.txt index 3bcec805ef..ec80ac6434 100644 --- a/docs/releases/5.0.txt +++ b/docs/releases/5.0.txt @@ -401,7 +401,9 @@ Management Commands Migrations ~~~~~~~~~~ -* ... +* Serialization of functions decorated with :func:`functools.cache` or + :func:`functools.lru_cache` is now supported without the need to write a + custom serializer. Models ~~~~~~ diff --git a/docs/topics/migrations.txt b/docs/topics/migrations.txt index 08d458fbb8..b7cd7043c2 100644 --- a/docs/topics/migrations.txt +++ b/docs/topics/migrations.txt @@ -788,6 +788,8 @@ Django can serialize the following: - Functions may be decorated if wrapped properly, i.e. using :func:`functools.wraps` + - The :func:`functools.cache` and :func:`functools.lru_cache` decorators are + explicitly supported - Unbound methods used from within the class body - Any class reference (must be in module's top-level scope) @@ -797,6 +799,11 @@ Django can serialize the following: Serialization support for ``enum.Flag`` was added. +.. versionchanged:: 5.0 + + Serialization support for functions decorated with :func:`functools.cache` + or :func:`functools.lru_cache` was added. + Django cannot serialize: - Nested classes diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py index e7c7917ef0..fd0e7f0fe3 100644 --- a/tests/migrations/test_writer.py +++ b/tests/migrations/test_writer.py @@ -90,6 +90,16 @@ def function_with_decorator(): pass +@functools.cache +def function_with_cache(): + pass + + +@functools.lru_cache(maxsize=10) +def function_with_lru_cache(): + pass + + class OperationWriterTests(SimpleTestCase): def test_empty_signature(self): operation = custom_migration_operations.operations.TestOperation() @@ -581,6 +591,8 @@ class WriterTests(SimpleTestCase): def test_serialize_decorated_functions(self): self.assertSerializedEqual(function_with_decorator) + self.assertSerializedEqual(function_with_cache) + self.assertSerializedEqual(function_with_lru_cache) def test_serialize_datetime(self): self.assertSerializedEqual(datetime.datetime.now())