Skip to content

Commit

Permalink
Merge branch 'master' into yaml-dataclass-tests
Browse files Browse the repository at this point in the history
This incorporates the changes from PRs #16, #17, and #18. This branch
was originally based on #16 before feedback.

I don't believe this introduces any new behavior
  • Loading branch information
ThirteenFish committed Feb 26, 2024
2 parents 8c71027 + e9e47b5 commit 60917b8
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 47 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,12 @@ OD.*

# Beacon def formats
*xtce.xml

# MacOS
.DS_Store

# Vim
*.swp

# setuptools-scm
*/_version.py
36 changes: 22 additions & 14 deletions oresat_configs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,28 @@
class OreSatConfig:
"""All the configs for an OreSat mission."""

def __init__(self, oresat: Union[OreSatId, Consts, str]):
if isinstance(oresat, str):
oresat = Consts.from_string(oresat)
elif isinstance(oresat, OreSatId):
oresat = Consts.from_id(oresat)
elif not isinstance(oresat, Consts):
raise TypeError(f"Unsupported oresat type: '{type(oresat)}'")

self.oresat = oresat
beacon_config = BeaconConfig.from_yaml(oresat.beacon_path)
self.cards = cards_from_csv(oresat)
self.configs = _load_configs(oresat.cards_path)
self.od_db = _gen_od_db(oresat, self.cards, beacon_config, self.configs)
def __init__(self, mission: Union[OreSatId, Consts, str]):
"""The parameter mission may be:
- a string, either short or long mission name ('0', 'OreSat0.5', ...)
- an OreSatId (ORESAT0, ...)
- a Consts (ORESAT0, ...)
It will be used to derive the appropriate Consts, the collection of
constants associated with a specific oresat mission.
"""
if isinstance(mission, str):
mission = Consts.from_string(mission)
elif isinstance(mission, OreSatId):
mission = Consts.from_id(mission)
elif not isinstance(mission, Consts):
raise TypeError(f"Unsupported mission type: '{type(mission)}'")

self.mission = mission
beacon_config = BeaconConfig.from_yaml(mission.beacon_path)
self.cards = cards_from_csv(mission)
self.configs = _load_configs(mission.cards_path)
self.od_db = _gen_od_db(mission, self.cards, beacon_config, self.configs)
c3_od = self.od_db["c3"]
self.beacon_def = _gen_c3_beacon_defs(c3_od, beacon_config)
self.fram_def = _gen_c3_fram_defs(c3_od, self.configs["c3"])
self.fw_base_od = _gen_fw_base_od(oresat, FW_COMMON_CONFIG_PATH)
self.fw_base_od = _gen_fw_base_od(mission, FW_COMMON_CONFIG_PATH)
36 changes: 19 additions & 17 deletions oresat_configs/__main__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
"""oresat_configs main"""

# Process for adding a new script:
# - Add module to scripts/ directory
# - It must have register_subparser() which takes a subparsers list
# - import the module here and add it to the SCRIPTS list
# - If it can also be a standalone script then update the pyproject.toml [project.scripts] section
#
# test it out - both through oresat_configs and directly
"""Entry point for for oresat_configs scripts. Invoke with either:
- python -m oresat_configs
- oresat-configs
Some scripts may be installed and run as a standalone program. Consult
pyproject.toml for names to invoke them with.
Process for adding a new script:
- Add as a module to the adjacent scripts/ directory. The module must have the
function register_subparser() which takes the output of
ArgumentParser.add_subparsers().
- Import the module here and add it to the _SCRIPTS list.
- If the script can also be standalone then update the pyproject.toml
[project.scripts] section.
- Test the new script out. Remember that the script may be invoked both through
oresat-configs and directly as a standalone.
"""

import argparse

Expand All @@ -21,7 +28,7 @@
# would have to be done through add_argument_group() but those can't
# make subparser groups.

SCRIPTS = [
_SCRIPTS = [
list_cards,
print_od,
sdo_transfer,
Expand All @@ -32,19 +39,14 @@
]


def oresat_configs() -> None:
"""oresat_configs main."""
if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="oresat_configs")
parser.add_argument("--version", action="version", version="%(prog)s v" + __version__)
parser.set_defaults(func=lambda x: parser.print_help())
subparsers = parser.add_subparsers(title="subcommands")

for subcommand in SCRIPTS:
for subcommand in _SCRIPTS:
subcommand.register_subparser(subparsers)

args = parser.parse_args()
args.func(args)


if __name__ == "__main__":
oresat_configs()
11 changes: 7 additions & 4 deletions oresat_configs/_yaml_to_od.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,10 @@ def _load_configs(config_paths: ConfigPaths) -> dict[str, CardConfig]:


def _gen_od_db(
oresat: Consts, cards: dict[str, Card], beacon_def: BeaconConfig, configs: dict[str, CardConfig]
mission: Consts,
cards: dict[str, Card],
beacon_def: BeaconConfig,
configs: dict[str, CardConfig],
) -> dict[str, ObjectDictionary]:
od_db = {}
node_ids = {name: cards[name].node_id for name in configs}
Expand Down Expand Up @@ -622,7 +625,7 @@ def _gen_od_db(

# set specific obj defaults
od["versions"]["configs_version"].default = __version__
od["satellite_id"].default = oresat.id
od["satellite_id"].default = mission.id
for sat in Consts:
od["satellite_id"].value_descriptions[sat.id] = sat.name.lower()
if name == "c3":
Expand Down Expand Up @@ -688,7 +691,7 @@ def _gen_c3_beacon_defs(c3_od: ObjectDictionary, beacon_def: BeaconConfig) -> li
return beacon_objs


def _gen_fw_base_od(oresat: Consts, config_path: str) -> canopen.ObjectDictionary:
def _gen_fw_base_od(mission: Consts, config_path: str) -> canopen.ObjectDictionary:
"""Generate all ODs for a OreSat mission."""

od = canopen.ObjectDictionary()
Expand Down Expand Up @@ -725,6 +728,6 @@ def _gen_fw_base_od(oresat: Consts, config_path: str) -> canopen.ObjectDictionar

# set specific obj defaults
od["versions"]["configs_version"].default = __version__
od["satellite_id"].default = oresat.id
od["satellite_id"].default = mission.id

return od
5 changes: 5 additions & 0 deletions oresat_configs/base/dxwifi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ objects:
description: number of images transmitted
access_type: ro

- subindex: 0x5
name: enable_pa
data_type: bool
description: enables the power amplifier
default: False


tpdos:
Expand Down
17 changes: 13 additions & 4 deletions oresat_configs/card_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import csv
import os
from dataclasses import dataclass
from dataclasses import dataclass, fields

from dataclasses_json import dataclass_json

Expand All @@ -28,11 +28,20 @@ class Card:
"""Optional child node name. Useful for CFC cards."""


def cards_from_csv(oresat: Consts) -> dict[str, Card]:
def cards_from_csv(mission: Consts) -> dict[str, Card]:
"""Turns cards.csv into a dict of names->Cards, filtered by the current mission"""

file_path = f"{os.path.dirname(os.path.abspath(__file__))}/cards.csv"
with open(file_path, "r") as f:
reader = csv.DictReader(f)
cols = set(reader.fieldnames) if reader.fieldnames else set()
expect = {f.name for f in fields(Card)}
expect.add("name") # the 'name' column is the keys of the returned dict; not in Card
if cols - expect:
raise TypeError(f"cards.csv has excess columns: {cols-expect}. Update class Card?")
if expect - cols:
raise TypeError(f"class Card expects more columns than cards.csv has: {expect-cols}")

return {
row["name"]: Card(
row["nice_name"],
Expand All @@ -42,6 +51,6 @@ def cards_from_csv(oresat: Consts) -> dict[str, Card]:
row["opd_always_on"].lower() == "true",
row["child"],
)
for row in csv.DictReader(f)
if row["name"] in oresat.cards_path
for row in reader
if row["name"] in mission.cards_path
}
13 changes: 12 additions & 1 deletion oresat_configs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,18 @@
from . import oresat0, oresat0_5, oresat1
from .base import ConfigPaths

__version__ = "0.3.1"
__all__ = [
"__version__",
"OreSatId",
"NodeId",
"Mission",
"Consts",
]

try:
from ._version import version as __version__ # type: ignore
except ImportError:
__version__ = "0.0.0" # package is not installed


@dataclass
Expand Down
4 changes: 2 additions & 2 deletions oresat_configs/scripts/gen_xtce.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ def write_xtce(config: OreSatConfig, dir_path: str = ".") -> None:
root = ET.Element(
"SpaceSystem",
attrib={
"name": str(config.oresat),
"name": str(config.mission),
"xmlns:xtce": "http://www.omg.org/space/xtce",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation": (
Expand Down Expand Up @@ -340,7 +340,7 @@ def write_xtce(config: OreSatConfig, dir_path: str = ".") -> None:
# write
tree = ET.ElementTree(root)
ET.indent(tree, space=" ", level=0)
file_name = f"{config.oresat.name.lower()}.xtce"
file_name = f"{config.mission.name.lower()}.xtce"
tree.write(f"{dir_path}/{file_name}", encoding="utf-8", xml_declaration=True)


Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["setuptools"]
requires = ["setuptools", "setuptools_scm"]
build-backend = "setuptools.build_meta"

[project]
Expand Down Expand Up @@ -33,15 +33,15 @@ oresat-print-od = "oresat_configs.scripts.print_od:print_od"
oresat-sdo-transfer = "oresat_configs.scripts.sdo_transfer:sdo_transfer"
oresat-gen-xtce = "oresat_configs.scripts.gen_xtce:gen_xtce"

[tool.setuptools.dynamic]
version = {attr = "oresat_configs.constants.__version__"}

[tool.setuptools.packages.find]
exclude = ["docs*", "tests*"]
exclude = ["docs*", "tests*"]

[tool.setuptools.package-data]
"*" = ["*.yaml", "*.csv"]

[tool.setuptools_scm]
write_to = "oresat_configs/_version.py"

[tool.black]
line_length = 100

Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pylama[toml]
pyyaml
types-pyyaml
setuptools
setuptools-scm
sphinx
sphinx-rtd-theme
tabulate
Expand Down

0 comments on commit 60917b8

Please sign in to comment.