diff --git a/ifex/model/ifex_ast_construction.py b/ifex/model/ifex_ast_construction.py index 21b06db5..79d9b08b 100644 --- a/ifex/model/ifex_ast_construction.py +++ b/ifex/model/ifex_ast_construction.py @@ -44,6 +44,7 @@ from collections import OrderedDict from dataclasses import is_dataclass, fields +from datetime import date, datetime from ifex.model import ifex_ast from ifex.model.type_checking_constructor_mixin import add_constructor @@ -67,6 +68,8 @@ def is_empty(node) -> bool: else: return node is None +def is_simple_type(t) -> bool: + return t in [str, int, float, bool, date, datetime] def ifex_ast_to_dict(node, debug_context="") -> OrderedDict: @@ -76,7 +79,7 @@ def ifex_ast_to_dict(node, debug_context="") -> OrderedDict: raise TypeError(f"None-value should not be passed to function, {debug_context=}") # Strings and Ints are directly understood by the YAML output printer so just put them in. - if type(node) in [str, int]: + if is_simple_type(type(node)): return node # In addition to dicts, we might have python lists, which will be output as lists in YAML @@ -95,13 +98,13 @@ def ifex_ast_to_dict(node, debug_context="") -> OrderedDict: # we skip them. Note that empty items can happen only on fields that are # Optional, otherwise the type-checking constructor would have caught the # error. - + for f in fields(node): item = getattr(node, f.name) if not is_empty(item): ret[f.name] = ifex_ast_to_dict(item, debug_context=str(f)) - return ret + return ret def ifex_ast_as_yaml(node): @@ -126,4 +129,3 @@ def ifex_ast_as_yaml(node): print(ifex_ast_to_dict(root)) print("\n--- Test objects as YAML: ---") print(ifex_ast_as_yaml(root)) - diff --git a/ifex/schema/ifex_to_json_schema.py b/ifex/schema/ifex_to_json_schema.py index 05afee92..c81b6754 100644 --- a/ifex/schema/ifex_to_json_schema.py +++ b/ifex/schema/ifex_to_json_schema.py @@ -14,6 +14,10 @@ """ from dataclasses import fields +from datetime import datetime, date + +from ifex.model.ifex_ast_construction import is_simple_type + from ifex.model.ifex_ast import AST from ifex.model.ifex_ast_introspect import actual_type, field_actual_type, field_inner_type, inner_type, is_forwardref, is_list, type_name, field_is_list, field_is_optional, field_referenced_type from typing import Any @@ -29,10 +33,18 @@ def get_type_name(t): if t is Any: return "Any" + if t is bool: + return "boolean" + elif t is datetime: + return "string" + elif t is date: + return "string" elif t is str: return "string" elif t is int: return "integer" + elif t is float: + return "number" else: # "complex type" return type_name(actual_type(t)) @@ -109,7 +121,7 @@ def collect_type_info(t, collection={}, seen={}): # We don't need to gather information about primitive types because they # will not have any member fields below them. - if t in [str, int, Any]: + if is_simple_type(t) or t is Any: return # ForwardRef will fail if we try to recurse over its children. However, diff --git a/tests/gen_test.py b/tests/gen_test.py index 1a574aa6..f7a83cd4 100644 --- a/tests/gen_test.py +++ b/tests/gen_test.py @@ -4,10 +4,19 @@ # Test code for code generator part of IFEX # ---------------------------------------------------------------------------- # This is maybe not ideal way but seems efficient enough +from dataclasses import dataclass +from datetime import date, datetime +from typing import Optional + +import yaml + from ifex.model import ifex_ast, ifex_parser, ifex_generator import dacite, pytest import os +from ifex.model.ifex_ast import Argument, AST, Namespace, Interface, Method +from ifex.model.ifex_ast_construction import ifex_ast_as_yaml + TestPath = os.path.dirname(os.path.realpath(__file__)) def test_x(): @@ -70,8 +79,54 @@ def test_expected_raised_exceptions(): with pytest.raises(dacite.UnexpectedDataError) as ee: ast_root = ifex_parser.get_ast_from_yaml_file(os.path.join(path, 'input.yaml')) +@dataclass +class Argument(Argument): + name: str + simple_type_str: Optional[str] = None + simple_type_int: Optional[int] = None + simple_type_bool: Optional[bool] = None + simple_type_float: Optional[float] = None + simple_type_date: Optional[date] = None + simple_type_datetime: Optional[datetime] = None + + +def test_simple_types(): + simple_types = yaml.safe_load(ifex_ast_as_yaml(AST(namespaces=[ + Namespace( + name="namespace1", + interface=Interface( + name="interface1", + methods=[ + Method( + name="method1", + input=[ + Argument( + name="argument1", + datatype="mixed", + simple_type_str="string", + simple_type_int=123, + simple_type_bool=True, + simple_type_float=123.45, + simple_type_date=date.today(), + simple_type_datetime=datetime.now() + ) + ] + ) + ] + ) + ) + ])))["namespaces"][0]["interface"]["methods"][0]["input"][0] + + assert type(simple_types["simple_type_str"]) == str + assert type(simple_types["simple_type_int"]) == int + assert type(simple_types["simple_type_bool"]) == bool + assert type(simple_types["simple_type_float"]) == float + assert type(simple_types["simple_type_date"]) == date + assert type(simple_types["simple_type_datetime"]) == datetime + + # Unused default_templates = {} # TODO: Loop over subdirectories in tests to perform tests for different -# 'input.yaml/template/result' files +# 'input.yaml/template/result' files \ No newline at end of file