Skip to content

Commit

Permalink
Merge branch 'devel' into fix/enum_representation_types
Browse files Browse the repository at this point in the history
  • Loading branch information
JackNWhite committed Oct 22, 2023
2 parents 3d0db04 + eada0c2 commit 8acb91f
Show file tree
Hide file tree
Showing 19 changed files with 196 additions and 125 deletions.
26 changes: 0 additions & 26 deletions .github/ISSUE_TEMPLATE/bug-report.md

This file was deleted.

11 changes: 11 additions & 0 deletions .github/ISSUE_TEMPLATE/do-not-use.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: Do not use
about: Please use https://github.com/nasa/fprime/issues instead
title: ''
labels: bug
assignees: ''

---
# Do not use

Please do not use this form. Issues should be posted to https://github.com/nasa/fprime/issues/new/choose
21 changes: 0 additions & 21 deletions .github/ISSUE_TEMPLATE/feature-request.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/fprime-gds-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.8", "3.9", "3.10", "3.11"]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gds-cli-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11"]

steps:

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# F´ GDS

Note: This README describes GDS internals. Refer to the [user's guide](https://nasa.github.io/fprime/UsersGuide/gds/gds-introduction.html)
for instructions on how to use the GDS.
**Note:** This README describes GDS internals. Refer to the [user's guide](https://nasa.github.io/fprime/UsersGuide/gds/gds-introduction.html) for instructions on how to use the GDS.

Issues should be reported here: [File an issue](https://github.com/nasa/fprime/issues/new/choose)

## Overview
The GDS consists of a collection of classes and tools that provide an interface for fprime
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
python_requires=">=3.7",
setup_requires=["setuptools_scm"],
install_requires=[
"flask>=1.1.2,<=2.2.3",
"flask>=3.0.0",
"flask_compress>=1.11",
"pyzmq>=24.0.1",
"pexpect>=4.8.0",
Expand All @@ -118,6 +118,6 @@
"argcomplete>=1.12.3",
"Jinja2>=2.11.3",
"openpyxl>=3.0.10",
"pyserial>=3.5"
"pyserial>=3.5",
],
)
12 changes: 9 additions & 3 deletions src/fprime_gds/common/data_types/event_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,15 @@ def __init__(self, event_args, event_time, event_temp):
self.args = event_args
self.time = event_time
self.template = event_temp
self.display_text = event_temp.description if event_args is None else format_string_template(
event_temp.format_str, tuple([arg.val for arg in event_args])
)
if event_args is None:
self.display_text = event_temp.description
elif event_temp.format_str == "":
args_template = self.template.get_args()
self.display_text = str([{args_template[index][0]:arg.val} for index, arg in enumerate(event_args)])
else:
self.display_text = format_string_template(
event_temp.format_str, tuple([arg.val for arg in event_args])
)

def get_args(self):
return self.args
Expand Down
28 changes: 21 additions & 7 deletions src/fprime_gds/flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@ def construct_app():
if "FP_FLASK_SETTINGS" in os.environ:
app.config.from_envvar("FP_FLASK_SETTINGS")

# JSON encoding setting must come before restful
app.json_encoder = fprime_gds.flask.json.GDSJsonEncoder
app.config["RESTFUL_JSON"] = {"cls": app.json_encoder}
# JSON encoding settings
app.json.default = fprime_gds.flask.json.default
app.config["RESTFUL_JSON"] = {"default": app.json.default}
# Standard pipeline creation
input_arguments = app.config["STANDARD_PIPELINE_ARGUMENTS"]
args_ns, _ = ParserBase.parse_args([StandardPipelineParser], "n/a", input_arguments, client=True)
args_ns, _ = ParserBase.parse_args(
[StandardPipelineParser], "n/a", input_arguments, client=True
)
pipeline = components.setup_pipelined_components(app.debug, args_ns)

# Restful API registration
Expand All @@ -83,7 +85,11 @@ def construct_app():
api.add_resource(
fprime_gds.flask.commands.CommandDictionary,
"/dictionary/commands",
resource_class_args=[pipeline.dictionaries.command_name, pipeline.dictionaries.project_version, pipeline.dictionaries.framework_version],
resource_class_args=[
pipeline.dictionaries.command_name,
pipeline.dictionaries.project_version,
pipeline.dictionaries.framework_version,
],
)
api.add_resource(
fprime_gds.flask.commands.CommandHistory,
Expand All @@ -98,7 +104,11 @@ def construct_app():
api.add_resource(
fprime_gds.flask.events.EventDictionary,
"/dictionary/events",
resource_class_args=[pipeline.dictionaries.event_id, pipeline.dictionaries.project_version, pipeline.dictionaries.framework_version],
resource_class_args=[
pipeline.dictionaries.event_id,
pipeline.dictionaries.project_version,
pipeline.dictionaries.framework_version,
],
)
api.add_resource(
fprime_gds.flask.events.EventHistory,
Expand All @@ -108,7 +118,11 @@ def construct_app():
api.add_resource(
fprime_gds.flask.channels.ChannelDictionary,
"/dictionary/channels",
resource_class_args=[pipeline.dictionaries.channel_id, pipeline.dictionaries.project_version, pipeline.dictionaries.framework_version],
resource_class_args=[
pipeline.dictionaries.channel_id,
pipeline.dictionaries.project_version,
pipeline.dictionaries.framework_version,
],
)
api.add_resource(
fprime_gds.flask.channels.ChannelHistory,
Expand Down
6 changes: 4 additions & 2 deletions src/fprime_gds/flask/default_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
#
####
import os
import getpass

# Select uploads directory and create it
uplink_dir = os.environ.get("UP_FILES_DIR", "/tmp/fprime-uplink/")
DOWNLINK_DIR = os.environ.get("DOWN_FILES_DIR", "/tmp/fprime-downlink/")
username = getpass.getuser()
uplink_dir = os.environ.get("UP_FILES_DIR", "/tmp/" + username + "/fprime-uplink/")
DOWNLINK_DIR = os.environ.get("DOWN_FILES_DIR", "/tmp/" + username + "/fprime-downlink/")

STANDARD_PIPELINE_ARGUMENTS = os.environ.get("STANDARD_PIPELINE_ARGUMENTS").split("|")

Expand Down
91 changes: 48 additions & 43 deletions src/fprime_gds/flask/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


def jsonify_base_type(input_type: Type[BaseType]) -> dict:
""" Turn a base type into a JSONable dictionary
"""Turn a base type into a JSONable dictionary
Convert a BaseType (the type, not an instance) into a jsonable dictionary. BaseTypes are converted by reading the
class properties (without __) and creating the object:
Expand All @@ -36,14 +36,17 @@ class properties
json-able dictionary representing the type
"""
assert issubclass(input_type, BaseType), "Failure to properly encode data"
members = getmembers(input_type, lambda value: not isroutine(value) and not isinstance(value, property))
members = getmembers(
input_type,
lambda value: not isroutine(value) and not isinstance(value, property),
)
jsonable_dict = {name: value for name, value in members if not name.startswith("_")}
jsonable_dict.update({"name": input_type.__name__})
return jsonable_dict


def getter_based_json(obj):
""" Converts objects to JSON via get_ methods
"""Converts objects to JSON via get_ methods
Template functions define a series of get_* methods whose return values need to be serialized. This function
handles that data.
Expand Down Expand Up @@ -80,7 +83,7 @@ def getter_based_json(obj):


def minimal_event(obj):
""" Minimal event encoding: time, id, display_text
"""Minimal event encoding: time, id, display_text
Events need time, id, display_text. No other information from the event is necessary for the display. This will
minimally encode the data for JSON.
Expand All @@ -95,7 +98,7 @@ def minimal_event(obj):


def minimal_channel(obj):
""" Minimal channel serialization: time, id, val, and display_text
"""Minimal channel serialization: time, id, val, and display_text
Minimally serializes channel values for use with the flask layer. This does away with any unnecessary data by
serializing only the id, value, and optional display text
Expand All @@ -106,11 +109,16 @@ def minimal_channel(obj):
Returns:
JSON compatible python anonymous type (dictionary)
"""
return {"time": obj.time, "id": obj.id, "val": obj.val_obj.val, "display_text": obj.display_text}
return {
"time": obj.time,
"id": obj.id,
"val": obj.val_obj.val,
"display_text": obj.display_text,
}


def minimal_command(obj):
""" Minimal command serialization: time, id, and args values
"""Minimal command serialization: time, id, and args values
Minimally serializes the command values for use with the flask layer. This prevents excess data by keeping the data
to the minimum instance data for commands including: time, opcode (id), and the value for args.
Expand All @@ -125,7 +133,7 @@ def minimal_command(obj):


def time_type(obj):
""" Time type serialization
"""Time type serialization
Serializes the time type into a JSON compatible object.
Expand All @@ -137,49 +145,46 @@ def time_type(obj):
"""
assert isinstance(obj, TimeType), "Incorrect type for serialization method"
return {
"base": obj.timeBase.value,
"context": obj.timeContext,
"seconds": obj.seconds,
"microseconds": obj.useconds
}
"base": obj.timeBase.value,
"context": obj.timeContext,
"seconds": obj.seconds,
"microseconds": obj.useconds,
}


def enum_json(obj):
""" Jsonify the python enums! """
"""Jsonify the python enums!"""
enum_dict = {"value": str(obj), "values": {}}
for enum_val in type(obj):
enum_dict["values"][str(enum_val)] = enum_val.value
return enum_dict


class GDSJsonEncoder(flask.json.JSONEncoder):
"""
Custom class used to handle GDS object to JSON
JSON_ENCODERS = {
ABCMeta: jsonify_base_type,
UUID: str,
ChData: minimal_channel,
EventData: minimal_event,
CmdData: minimal_command,
TimeType: time_type,
}


def default(obj):
"""
JSON_ENCODERS = {
ABCMeta: jsonify_base_type,
UUID: str,
ChData: minimal_channel,
EventData: minimal_event,
CmdData: minimal_command,
TimeType: time_type
}
Override the default JSON encoder to pull out a dictionary for our handled types for encoding with the default
encoder built into flask. This function must convert the given object into a JSON compatable python object (e.g.
using lists, dictionaries, strings, and primitive types).
def default(self, obj):
"""
Override the default JSON encoder to pull out a dictionary for our handled types for encoding with the default
encoder built into flask. This function must convert the given object into a JSON compatable python object (e.g.
using lists, dictionaries, strings, and primitive types).
:param obj: obj to encode
:return: JSON
"""
if type(obj) in self.JSON_ENCODERS:
return self.JSON_ENCODERS[type(obj)](obj)
if isinstance(obj, DataTemplate):
return getter_based_json(obj)
if isinstance(obj, Enum):
return enum_json(obj)
if isinstance(obj, ValueType):
return obj.val
return flask.json.JSONEncoder.default(self, obj)
:param obj: obj to encode
:return: JSON
"""
if type(obj) in JSON_ENCODERS:
return JSON_ENCODERS[type(obj)](obj)
if isinstance(obj, DataTemplate):
return getter_based_json(obj)
if isinstance(obj, Enum):
return enum_json(obj)
if isinstance(obj, ValueType):
return obj.val
return flask.json.provider.DefaultJSONProvider.default(obj)
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export let advanced_template = `
<h3>{{ setting_category.replace("_", " ") }}</h3>
<div v-html="settings[setting_category].description"></div>
<div class="input-group mb-3" v-for="setting_key in Object.keys(settings[setting_category].settings)">
<small v-if="(settings[setting_category].descriptions || {})[setting_key]">
<strong>{{ setting_key }}</strong>
{{ settings[setting_category].descriptions[setting_key]}}
</small>
<div class="input-group-prepend col-6">
<span class="input-group-text col-12">{{ setting_key }}</span>
</div>
Expand Down
20 changes: 13 additions & 7 deletions src/fprime_gds/flask/static/addons/advanced-settings/addon.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ Vue.component("advanced-settings", {
settings: _settings.polling_intervals
},
"Miscellaneous": {
description: "Miscellaneous settings for GDS UI operations." +
"<small><ul>" +
"<li>event_buffer_size: maximum event records. Default: -1, infinite.</li>" +
"<li>command_buffer_size: maximum command history records. Default: -1, infinite.</li>" +
"<li>response_object_limit: maximum results to load per polling request. Default: 6000</li>" +
'<li>compact_commanding: use compact "flattened" style for commanding complex arguments.</li>' +
"</ul></small>",
description: "Miscellaneous settings for GDS UI operations.",
descriptions: {
event_buffer_size: "Maximum number of events stored by the GDS. When exceeded, oldest events are dropped " +
"Lower this value if performance drops on the Events tab. Default: -1, no limit.",
command_buffer_size: "Maximum number of commands stored by the GDS. When exceeded, oldest commands are dropped " +
"Lower this value if performance drops on the Commanding tab. Default: -1, no limit.",
response_object_limit: "Limit to the number of objects returned by one POLL request to the backend. " +
"Lower this value if polling times are longer than polling intervals. Default: 6000.",
compact_commanding: "Use the compact form for command arguments. In this form, Array and Serializable type " +
"inputs are flattened into a sequential set of input boxes without extraneous structure.",
channels_display_last_received: "When set, any channel received will update the displayed value. Otherwise " +
"only channels with newer timestamps update the displayed value."
},
settings: _settings.miscellaneous
}
},
Expand Down
Loading

0 comments on commit 8acb91f

Please sign in to comment.