]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Fix pickle/copy support for the `missing` singleton 2029/head
authorMatt Clay <matt@mystile.com>
Tue, 1 Oct 2024 22:18:27 +0000 (15:18 -0700)
committerDavid Lord <davidism@gmail.com>
Thu, 19 Dec 2024 16:19:07 +0000 (08:19 -0800)
CHANGES.rst
src/jinja2/utils.py
tests/test_utils.py

index 58dc032145a7b4cc1fc9104351ac51eb7ebec430..1a1a526b5fe9f98c2367fd7e66da7ccabd0e9d9d 100644 (file)
@@ -24,6 +24,8 @@ Unreleased
     call. :issue:`2021`
 -   Fix dunder protocol (`copy`/`pickle`/etc) interaction with ``Undefined``
     objects. :issue:`2025`
+-   Fix `copy`/`pickle` support for the internal ``missing`` object.
+    :issue:`2027`
 
 
 Version 3.1.4
index 5c1ff5d7ba751c18c29346b829228e885cd202de..7b52fc03e08df61ce55246fb8121ef1b182ee5a1 100644 (file)
@@ -18,8 +18,17 @@ if t.TYPE_CHECKING:
 
 F = t.TypeVar("F", bound=t.Callable[..., t.Any])
 
-# special singleton representing missing values for the runtime
-missing: t.Any = type("MissingType", (), {"__repr__": lambda x: "missing"})()
+
+class _MissingType:
+    def __repr__(self) -> str:
+        return "missing"
+
+    def __reduce__(self) -> str:
+        return "missing"
+
+
+missing: t.Any = _MissingType()
+"""Special singleton representing missing values for the runtime."""
 
 internal_code: t.MutableSet[CodeType] = set()
 
index 7b58af144e254eb750db413dfaae9367c27e3104..86e0f0420fc70e59693cb9d62074041432fab50c 100644 (file)
@@ -1,3 +1,4 @@
+import copy
 import pickle
 import random
 from collections import deque
@@ -183,3 +184,14 @@ def test_consume():
     consume(x)
     with pytest.raises(StopIteration):
         next(x)
+
+
+@pytest.mark.parametrize("protocol", range(pickle.HIGHEST_PROTOCOL + 1))
+def test_pickle_missing(protocol: int) -> None:
+    """Test that missing can be pickled while remaining a singleton."""
+    assert pickle.loads(pickle.dumps(missing, protocol)) is missing
+
+
+def test_copy_missing() -> None:
+    """Test that missing can be copied while remaining a singleton."""
+    assert copy.copy(missing) is missing