]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
python: utils/modeling: fixed Literal bug for python 3.8
authorAleš Mrázek <ales.mrazek@nic.cz>
Wed, 21 Jan 2026 20:28:44 +0000 (21:28 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 27 Jan 2026 08:44:38 +0000 (09:44 +0100)
This fixes bug created in MR !1768 logging improvements.

python/knot_resolver/utils/modeling/base_schema.py
tests/manager/utils/modeling/test_base_schema.py

index 93e59b9bd7245de17ada4ca2ea377dfd4db410a1..6e83719d2a0ee67d09580ae83a104e644843d5f1 100644 (file)
@@ -1,5 +1,6 @@
 import enum
 import inspect
+import sys
 from abc import ABC, abstractmethod  # pylint: disable=[no-name-in-module]
 from typing import Any, Callable, Dict, Generic, List, Optional, Set, Tuple, Type, TypeVar, Union, cast
 
@@ -354,7 +355,18 @@ class ObjectMapper:
         raise DataValidationError(f"expected bool, found {type(obj)}", object_path)
 
     def _create_literal(self, tp: Type[Any], obj: Any, object_path: str) -> Any:
-        expected = get_generic_type_arguments(tp)
+        args = get_generic_type_arguments(tp)
+
+        expected = []
+        if sys.version_info < (3, 9):
+            for arg in args:
+                if is_literal(arg):
+                    expected += get_generic_type_arguments(arg)
+                else:
+                    expected.append(arg)
+        else:
+            expected = args
+
         if obj in expected:
             return obj
         raise DataValidationError(f"'{obj}' does not match any of the expected values {expected}", object_path)
index 3269961745c18a46c4c3d8f97902909e523e0e18..cb45f2211afc594cf91d29e615caa02f8b37b70f 100644 (file)
@@ -19,6 +19,21 @@ class _TestStr(ConfigSchema):
     v: str
 
 
+class _TestLiteral(ConfigSchema):
+    v: Literal[Literal["lit1"], Literal["lit2"]]
+
+
+@pytest.mark.parametrize("val", ["lit1", "lit2"])
+def test_parsing_literal_valid(val: str):
+    assert _TestLiteral(parse_yaml(f"v: {val}")).v == val
+
+
+@pytest.mark.parametrize("val", ["invalid", "false", 1, "null"])
+def test_parsing_literal_invalid(val: str):
+    with raises(DataValidationError):
+        _TestLiteral(parse_yaml(f"v: {val}"))
+
+
 @pytest.mark.parametrize("val,exp", [("false", False), ("true", True), ("False", False), ("True", True)])
 def test_parsing_bool_valid(val: str, exp: bool):
     assert _TestBool(parse_yaml(f"v: {val}")).v == exp