diff --git a/json_to_models/dynamic_typing/complex.py b/json_to_models/dynamic_typing/complex.py index 5d42439..156a9cd 100644 --- a/json_to_models/dynamic_typing/complex.py +++ b/json_to_models/dynamic_typing/complex.py @@ -1,3 +1,4 @@ +import json from functools import partial from itertools import chain from typing import AbstractSet, Dict, Iterable, List, Optional, Tuple, Type, Union @@ -266,7 +267,7 @@ def to_typing_code(self, types_style: Dict[Union['BaseType', Type['BaseType']], limit = options.get(self.TypeStyle.max_literals) if limit is None or len(self.literals) < limit: parts = ', '.join( - '"{}"'.format(s.replace('\\', '\\\\').replace('"', '\\"')) + json.dumps(s) for s in sorted(self.literals) ) return [(Literal.__module__, 'Literal')], f"Literal[{parts}]" diff --git a/test/test_code_generation/test_models_code_generator.py b/test/test_code_generation/test_models_code_generator.py index d3200db..a29547f 100644 --- a/test/test_code_generation/test_models_code_generator.py +++ b/test/test_code_generation/test_models_code_generator.py @@ -3,7 +3,21 @@ import pytest from typing_extensions import Literal -from json_to_models.dynamic_typing import (AbsoluteModelRef, BaseType, DDict, DList, DOptional, IntString, IsoDateString, ModelMeta, ModelPtr, StringLiteral, StringSerializable, Unknown, compile_imports) +from json_to_models.dynamic_typing import ( + AbsoluteModelRef, + BaseType, + DDict, + DList, + DOptional, + IntString, + IsoDateString, + ModelMeta, + ModelPtr, + StringLiteral, + StringSerializable, + Unknown, + compile_imports, +) from json_to_models.models.base import GenericModelCodeGenerator, generate_code from json_to_models.models.structure import sort_fields from json_to_models.models.utils import indent @@ -146,6 +160,39 @@ class Test: d: Dict[str, Any] baz: Optional[List[List[str]]] """) + }, + "literals": { + "model": ("Test", { + "a": StringLiteral({'basic'}), + "b": StringLiteral({'with space'}), + "c": StringLiteral({'with\ttab'}), + "d": StringLiteral({'with\nnew_line'}), + "e": StringLiteral({'with \'"qoutes"\''}), + "f": StringLiteral({'with \\ // slash'}), + }), + "fields": { + "imports": f"{LITERAL_SOURCE} import Literal", + "fields": [ + 'a: Literal["basic"]', + 'b: Literal["with space"]', + 'c: Literal["with\\ttab"]', + 'd: Literal["with\\nnew_line"]', + 'e: Literal["with \'\\"qoutes\\"\'"]', + 'f: Literal["with \\\\ // slash"]' + ] + }, + "generated": trim(f""" + {LITERAL_SOURCE} import Literal + + + class Test: + a: Literal["basic"] + b: Literal["with space"] + c: Literal["with\\ttab"] + d: Literal["with\\nnew_line"] + e: Literal["with \'\\"qoutes\\"\'"] + f: Literal["with \\\\ // slash"] + """) } }