From b0ae3ecf21068a3bcc89e7973b47786d0847a119 Mon Sep 17 00:00:00 2001 From: bogdandm Date: Thu, 18 Apr 2019 13:14:56 +0300 Subject: [PATCH] Process empty dict as Dict type --- TODO.md | 2 +- json_to_models/generator.py | 6 +++--- json_to_models/registry.py | 4 ++-- .../test_models_code_generator.py | 17 ++++++++++++----- test/test_generator/test_detect_type.py | 3 ++- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/TODO.md b/TODO.md index 1a71360..01846a8 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,7 @@ - Features - Models layer - [X] Data variant converting - - [ ] Change empty dict to actual dict type, not empty models + - [X] Change empty dict to actual dict type, not empty models - [X] Data variant merging - [X] Create and register models - [X] Merge meta-models and extract common ones diff --git a/json_to_models/generator.py b/json_to_models/generator.py index d67de0c..fa563f0 100644 --- a/json_to_models/generator.py +++ b/json_to_models/generator.py @@ -77,6 +77,8 @@ def _detect_type(self, value, convert_dict=True) -> MetaData: # Dict should be processed as another model if convert_dict is enabled elif isinstance(value, dict): + if not value: + return DDict(Unknown) for reg in self.dict_keys_regex: if all(map(reg.match, value.keys())): convert_dict = False @@ -91,10 +93,8 @@ def _detect_type(self, value, convert_dict=True) -> MetaData: if len(union.types) == 1: return DDict(*union.types) return DDict(union) - elif types: - return DDict(*types) else: - return DDict(Unknown) + return DDict(*types) # null interpreted as is and will be processed later on Union merge stage elif value is None: diff --git a/json_to_models/registry.py b/json_to_models/registry.py index 2e7c800..4818392 100644 --- a/json_to_models/registry.py +++ b/json_to_models/registry.py @@ -1,6 +1,6 @@ from collections import OrderedDict, defaultdict from itertools import chain, combinations -from typing import Dict, List, Set, Tuple +from typing import Dict, Iterable, List, Set, Tuple from ordered_set import OrderedSet @@ -147,7 +147,7 @@ def merge_models(self, generator, strict=False) -> List[Tuple[ModelMeta, Set[Mod models2merge[model_b].add(model_a) # Groups of models to merge - groups: List[Set[ModelMeta]] = [{model, *models} for model, models in models2merge.items()] + groups: Iterable[Set[ModelMeta]] = [{model, *models} for model, models in models2merge.items()] # Make groups non-overlapping. # This is not optimal algorithm but it works and we probably will not have thousands of models here. flag = True diff --git a/test/test_code_generation/test_models_code_generator.py b/test/test_code_generation/test_models_code_generator.py index 0ad7184..a2d5d1b 100644 --- a/test/test_code_generation/test_models_code_generator.py +++ b/test/test_code_generation/test_models_code_generator.py @@ -2,8 +2,8 @@ import pytest -from json_to_models.dynamic_typing import (AbsoluteModelRef, DList, DOptional, IntString, ModelMeta, ModelPtr, - compile_imports) +from json_to_models.dynamic_typing import (AbsoluteModelRef, DDict, DList, DOptional, IntString, ModelMeta, ModelPtr, + Unknown, compile_imports) from json_to_models.models import indent, sort_fields from json_to_models.models.base import GenericModelCodeGenerator, generate_code @@ -101,7 +101,8 @@ class Test: "model": ("Test", { "foo": int, "baz": DOptional(DList(DList(str))), - "bar": IntString + "bar": IntString, + "d": DDict(Unknown) }), "fields_data": { "foo": { @@ -115,25 +116,31 @@ class Test: "bar": { "name": "bar", "type": "IntString" + }, + "d": { + "name": "d", + "type": "Dict[str, Any]" } }, "fields": { "imports": "from json_to_models.dynamic_typing import IntString\n" - "from typing import List, Optional", + "from typing import Any, Dict, List, Optional", "fields": [ "foo: int", "bar: IntString", + "d: Dict[str, Any]", "baz: Optional[List[List[str]]]", ] }, "generated": trim(""" from json_to_models.dynamic_typing import IntString - from typing import List, Optional + from typing import Any, Dict, List, Optional class Test: foo: int bar: IntString + d: Dict[str, Any] baz: Optional[List[List[str]]] """) } diff --git a/test/test_generator/test_detect_type.py b/test/test_generator/test_detect_type.py index e1589c7..3404757 100644 --- a/test/test_generator/test_detect_type.py +++ b/test/test_generator/test_detect_type.py @@ -17,7 +17,8 @@ pytest.param("1", IntString, id="int_str"), pytest.param("1.0", FloatString, id="float_str"), pytest.param("true", BooleanString, id="bool_str"), - pytest.param({"test_dict_field_a": 1, "test_dict_field_b": "a"}, DDict(DUnion(int, str)), id="dict") + pytest.param({"test_dict_field_a": 1, "test_dict_field_b": "a"}, DDict(DUnion(int, str)), id="dict"), + pytest.param({}, DDict(Unknown)) ] test_dict = {param.id: param.values[0] for param in test_data}