Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #109: Fundamental types used in ifex_ast.py #110

Merged
merged 2 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions ifex/model/ifex_ast_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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:

Expand All @@ -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
Expand All @@ -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):
Expand All @@ -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))

14 changes: 13 additions & 1 deletion ifex/schema/ifex_to_json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))

Expand Down Expand Up @@ -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,
Expand Down
57 changes: 56 additions & 1 deletion tests/gen_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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
Loading