Skip to content

Commit

Permalink
Translate format strings at load-time
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-bc committed Apr 26, 2024
1 parent e595fe3 commit 07d6f62
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 130 deletions.
5 changes: 4 additions & 1 deletion src/fprime_gds/common/loaders/ch_json_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ def construct_template_from_dict(self, channel_dict: dict):
channel_name = channel_dict[self.NAME_FIELD].split(".")[1]
channel_type = channel_dict.get("type")
type_obj = self.parse_type(channel_type)
format_str = JsonLoader.preprocess_format_str(
channel_dict.get(self.FMT_STR_FIELD)
)

limit_field = channel_dict.get(self.LIMIT_FIELD)
limit_low = limit_field.get(self.LIMIT_LOW) if limit_field else None
Expand All @@ -81,7 +84,7 @@ def construct_template_from_dict(self, channel_dict: dict):
channel_name,
component_name,
type_obj,
ch_fmt_str=channel_dict.get(self.FMT_STR_FIELD),
ch_fmt_str=format_str,
ch_desc=channel_dict.get(self.DESC_FIELD),
low_red=limit_low_red,
low_orange=limit_low_orange,
Expand Down
10 changes: 5 additions & 5 deletions src/fprime_gds/common/loaders/ch_xml_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ def construct_dicts(self, path):
respectively and the values are ChTemplate objects
"""
xml_tree = self.get_xml_tree(path)
versions = xml_tree.attrib.get("framework_version", "unknown"), xml_tree.attrib.get("project_version", "unknown")
versions = xml_tree.attrib.get(
"framework_version", "unknown"
), xml_tree.attrib.get("project_version", "unknown")

# Check if xml dict has channels section
ch_section = self.get_xml_section(self.CH_SECT, xml_tree)
if ch_section is None:
msg = f"Xml dict did not have a {self.CH_SECT} section"
raise exceptions.GseControllerParsingException(
msg
)
raise exceptions.GseControllerParsingException(msg)

id_dict = {}
name_dict = {}
Expand All @@ -84,7 +84,7 @@ def construct_dicts(self, path):
ch_desc = ch_dict[self.DESC_TAG]

if self.FMT_STR_TAG in ch_dict:
ch_fmt_str = ch_dict[self.FMT_STR_TAG]
ch_fmt_str = XmlLoader.preprocess_format_str(ch_dict[self.FMT_STR_TAG])

# TODO we need to convert these into numbers, is this the best
# way to do it?
Expand Down
4 changes: 3 additions & 1 deletion src/fprime_gds/common/loaders/event_json_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ def construct_dicts(self, path):
event_id = event_dict[self.ID_TAG]
event_severity = EventSeverity[event_dict[self.SEVERITY_TAG]]

event_fmt_str = event_dict.get(self.FMT_STR_TAG, "")
event_fmt_str = JsonLoader.preprocess_format_str(
event_dict.get(self.FMT_STR_TAG, "")
)

event_desc = event_dict.get(self.DESC_TAG)

Expand Down
16 changes: 10 additions & 6 deletions src/fprime_gds/common/loaders/event_xml_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ def construct_dicts(self, path):
respectively and the values are ChTemplate objects
"""
xml_tree = self.get_xml_tree(path)
versions = xml_tree.attrib.get("framework_version", "unknown"), xml_tree.attrib.get("project_version", "unknown")
versions = xml_tree.attrib.get(
"framework_version", "unknown"
), xml_tree.attrib.get("project_version", "unknown")

# Check if xml dict has events section
event_section = self.get_xml_section(self.EVENT_SECT, xml_tree)
if event_section is None:
msg = f"Xml dict did not have a {self.EVENT_SECT} section"
raise exceptions.GseControllerParsingException(
msg
)
raise exceptions.GseControllerParsingException(msg)

id_dict = {}
name_dict = {}
Expand All @@ -63,14 +63,18 @@ def construct_dicts(self, path):
event_name = event_dict[self.NAME_TAG]
event_id = int(event_dict[self.ID_TAG], base=16)
event_severity = EventSeverity[event_dict[self.SEVERITY_TAG]]
event_fmt_str = event_dict[self.FMT_STR_TAG]
event_fmt_str = XmlLoader.preprocess_format_str(
event_dict[self.FMT_STR_TAG]
)

event_desc = None
if self.DESC_TAG in event_dict:
event_desc = event_dict[self.DESC_TAG]

# Parse arguments
args = self.get_args_list(event, xml_tree, f"{ event_comp }::{ event_name }")
args = self.get_args_list(
event, xml_tree, f"{ event_comp }::{ event_name }"
)

event_temp = EventTemplate(
event_id,
Expand Down
34 changes: 18 additions & 16 deletions src/fprime_gds/common/loaders/json_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,16 @@
)
from fprime.common.models.serialize.serializable_type import SerializableType
from fprime.common.models.serialize.string_type import StringType
from fprime.common.models.serialize.type_base import DictionaryType, BaseType
from fprime.common.models.serialize.type_base import BaseType

from typing import Optional

# Custom Python Modules
from . import dict_loader

import json
from fprime_gds.common.utils.string_util import preprocess_fpp_format_str

Check failure on line 34 in src/fprime_gds/common/loaders/json_loader.py

View workflow job for this annotation

GitHub Actions / Spell checking

`fpp` is not a recognized word. (unrecognized-spelling)

# FORMAT_STR_MAP = {
# "U8": "%u",
# "I8": "%d",
# "U16": "%u",
# "I16": "%d",
# "U32": "%u",
# "I32": "%d",
# "U64": "%lu",
# "I64": "%ld",
# "F32": "%g",
# "F64": "%g",
# "bool": "%s",
# "string": "%s",
# "ENUM": "%d",
# }

PRIMITIVE_TYPE_MAP = {
"I8": I8Type,
Expand Down Expand Up @@ -172,3 +159,18 @@ def parse_type(self, type_dict: dict) -> BaseType:
raise ValueError(
f"Channel entry in dictionary has unknown type {str(type_dict)}"
)

@staticmethod
def preprocess_format_str(format_str: Optional[str]) -> str:
"""Preprocess format strings before using them in Python format function
Internally, this converts FPP-style format strings to Python-style format strings
Args:
format_str (str): FPP-style format string
Returns:
str: Python-style format string
"""
if format_str is None:
return None
return preprocess_fpp_format_str(format_str)

Check failure on line 176 in src/fprime_gds/common/loaders/json_loader.py

View workflow job for this annotation

GitHub Actions / Spell checking

`fpp` is not a recognized word. (unrecognized-spelling)
40 changes: 31 additions & 9 deletions src/fprime_gds/common/loaders/xml_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@bug No known bugs
"""

import os

from fprime.common.models.serialize.array_type import ArrayType
Expand All @@ -34,6 +35,7 @@
from fprime.common.models.serialize.string_type import StringType
from lxml import etree

from fprime_gds.common.utils.string_util import preprocess_c_style_format_str
from fprime_gds.common.data_types import exceptions
from fprime_gds.version import (
MAXIMUM_SUPPORTED_FRAMEWORK_VERSION,
Expand Down Expand Up @@ -258,18 +260,21 @@ def get_serializable_type(self, type_name, xml_obj):
members = []
for memb in memb_section:
name = memb.get(self.SER_MEMB_NAME_TAG)
fmt_str = memb.get(self.SER_MEMB_FMT_STR_TAG)
fmt_str = XmlLoader.preprocess_format_str(
memb.get(self.SER_MEMB_FMT_STR_TAG)
)
desc = memb.get(self.SER_MEMB_DESC_TAG)
memb_type_name = memb.get(self.SER_MEMB_TYPE_TAG)
memb_size = memb.get(self.SER_MEMB_SIZE_TAG)
type_obj = self.parse_type(memb_type_name, memb, xml_obj)
# memb_size is not None for member array
if(memb_size is not None):
if memb_size is not None:
type_obj = ArrayType.construct_type(
f"Array_{type_obj.__name__}_{memb_size}",
type_obj,
int(memb_size),
fmt_str)
fmt_str,
)

members.append((name, type_obj, fmt_str, desc))

Expand Down Expand Up @@ -319,10 +324,14 @@ def get_array_type(self, type_name, xml_obj):
# Make config
arr_type = arr_memb.get(self.ARR_TYPE_TAG)
type_obj = self.parse_type(arr_type, arr_memb, xml_obj)
arr_format = arr_memb.get(self.ARR_FORMAT_TAG)
arr_format = XmlLoader.preprocess_format_str(
arr_memb.get(self.ARR_FORMAT_TAG)
)
arr_size = arr_memb.get(self.ARR_SIZE_TAG)

arr_obj = ArrayType.construct_type(type_name, type_obj, int(arr_size), arr_format)
arr_obj = ArrayType.construct_type(
type_name, type_obj, int(arr_size), arr_format
)

self.array_types[type_name] = arr_obj
return arr_obj
Expand Down Expand Up @@ -372,7 +381,9 @@ def parse_type(self, type_name, xml_item, xml_tree, context=None):
return BoolType
if type_name == "string":
if self.STR_LEN_TAG not in xml_item.attrib:
print(f"Trying to parse string type, but found {self.STR_LEN_TAG} field")
print(
f"Trying to parse string type, but found {self.STR_LEN_TAG} field"
)
return None
max_length = int(xml_item.get(self.STR_LEN_TAG, 0))
name = f"{context or ''}::{xml_item.get(self.ARG_NAME_TAG)}String"
Expand All @@ -394,6 +405,17 @@ def parse_type(self, type_name, xml_item, xml_tree, context=None):

# Abandon all hope
msg = f"Could not find type {type_name}"
raise exceptions.GseControllerParsingException(
msg
)
raise exceptions.GseControllerParsingException(msg)

@staticmethod
def preprocess_format_str(format_str):
"""Converts C-style format strings to Python-style format strings
For example "%x" -> "{:x}" or "%.2f" -> "{:.2f}"
Args:
format_str (str): C-style format string
Returns:
str: Python-style format string
"""
return preprocess_c_style_format_str(format_str)
Loading

0 comments on commit 07d6f62

Please sign in to comment.