from .generic_types import ListOrItem
from .types import (
DomainName,
+ EscapedStr,
IDPattern,
Int0_512,
Int0_65535,
"PolicyFlagEnum",
"DNSRecordTypeEnum",
"DomainName",
+ "EscapedStr",
"IDPattern",
"Int0_512",
"Int0_65535",
return self._base_value
+class EscapedStr(StrBase):
+ """
+ A string where escape sequences are ignored and quotes are escaped.
+ """
+
+ def __init__(self, source_value: Any, object_path: str = "/") -> None:
+ super().__init__(source_value, object_path)
+
+ escape = {
+ "'": r"\'",
+ '"': r"\"",
+ "\a": r"\a",
+ "\n": r"\n",
+ "\r": r"\r",
+ "\t": r"\t",
+ "\b": r"\b",
+ "\f": r"\f",
+ "\v": r"\v",
+ "\0": r"\0",
+ }
+
+ s = list(self._value)
+ for i, c in enumerate(self._value):
+ if c in escape:
+ s[i] = escape[c]
+ elif not c.isalnum():
+ s[i] = repr(c)[1:-1]
+ self._value = "".join(s)
+
+
class DomainName(StrBase):
"""
Fully or partially qualified domain name.
--- /dev/null
+from typing import Any
+
+import pytest
+from jinja2 import Template
+
+from knot_resolver_manager.datamodel.types import EscapedStr
+from knot_resolver_manager.utils.modeling import ConfigSchema
+
+str_template = Template("'{{ string }}'")
+
+
+@pytest.mark.parametrize(
+ "val,exp",
+ [
+ ("", ""),
+ ("string", "string"),
+ (2000, "2000"),
+ ('"\a\b\f\n\r\t\v\\"', r"\"\a\b\f\n\r\t\v\\\""),
+ ('""', r"\"\""),
+ ("''", r"\'\'"),
+ # fmt: off
+ ('\"\"', r'\"\"'),
+ ("\'\'", r'\'\''),
+ # fmt: on
+ ],
+)
+def test_escaped_str(val: Any, exp: str):
+ class TestSchema(ConfigSchema):
+ pattern: EscapedStr
+
+ d = TestSchema({"pattern": val})
+ assert str_template.render(string=d.pattern) == f"'{exp}'"
from knot_resolver_manager.datamodel.types import (
Dir,
DomainName,
+ EscapedStr,
InterfaceName,
InterfaceOptionalPort,
InterfacePort,
PinSha256(val)
+@pytest.mark.parametrize(
+ "val,exp",
+ [
+ ("", r""),
+ (2000, "2000"),
+ ("string", r"string"),
+ ("\t\n\v", r"\t\n\v"),
+ ("\a\b\f\n\r\t\v\\", r"\a\b\f\n\r\t\v\\"),
+ # fmt: off
+ ("''", r"\'\'"),
+ ('""', r'\"\"'),
+ ("\'\'", r"\'\'"),
+ ('\"\"', r'\"\"'),
+ ('\\"\\"', r'\\\"\\\"'),
+ ("\\'\\'", r"\\\'\\\'"),
+ # fmt: on
+ ],
+)
+def test_escaped_str_valid(val: Any, exp: str):
+ assert str(EscapedStr(val)) == exp
+
+
+@pytest.mark.parametrize("val", [1.1, False])
+def test_escaped_str_invalid(val: Any):
+ with raises(ValueError):
+ EscapedStr(val)
+
+
@pytest.mark.parametrize(
"val",
[