Skip to content

Commit

Permalink
Merge pull request #20 from oresat/fast-oresatconfig
Browse files Browse the repository at this point in the history
Faster OreSatConfig() creation
  • Loading branch information
ryanpdx authored Feb 26, 2024
2 parents 7e24512 + 869e399 commit e250690
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 54 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ jobs:
timeout-minutes: 10

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python 3.9
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: "3.9"
cache: "pip"

- name: Install dependencies
run: |
sudo apt install libyaml-0-2
python -m pip install --upgrade pip
pip install -r requirements.txt
Expand Down
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,31 @@ transfers.

## Setup

Install project dev dependencies.
Install project dev dependencies. `libyaml` should be installed by default on
reasonable systems, but it never hurts to make sure.

```bash
$ sudo apt install libyaml-0-2
$ pip install -r requirements.txt
```

If installing on ARM (e.g. Octavo cards like the C3) special work is needed to
ensure that `pyyaml` uses the `libyaml` C bindings. The binary wheels from PyPI
aren't built with them so we need to install from the source package:

Installing the first time:
```bash
$ sudo apt install libyaml-dev
$ pip install --no-binary pyyaml -r requirements.txt
```

Fixing an already installed pyyaml: (see here if you get "ImportError: pyyaml
missing/installed without libyaml bindings.")
```bash
$ sudo apt install libyaml-dev
$ pip install --no-cache-dir --no-binary pyyaml pyyaml
```

## Updating a Config

After updating configs for card(s), run the unit tests to validate all the
Expand Down
11 changes: 11 additions & 0 deletions oresat_configs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
"""OreSat OD database"""

# Checks that pyyaml is installed correctly. For performance reasons it must use the libyaml C
# bindings. To use them both libyaml must be installed on the local system, and pyyaml must have
# been built to use them. This works correctly on x86 systems, but on arm pyyaml is built by
# default to not include the bindings.
try:
from yaml import CLoader
except ImportError as e:
raise ImportError(
"pyyaml missing/installed without libyaml bindings. See oresat-configs README.md for more"
) from e

from dataclasses import dataclass
from typing import Union

Expand Down
15 changes: 5 additions & 10 deletions oresat_configs/_yaml_to_od.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@

import os
from copy import deepcopy
from typing import Any, Union
from typing import Union

import canopen
from canopen import ObjectDictionary
from canopen.objectdictionary import Array, Record, Variable
from yaml import load

Loader: Any
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader
from dacite import from_dict
from yaml import CLoader, load

from .base import ConfigPaths
from .beacon_config import BeaconConfig
Expand Down Expand Up @@ -474,11 +469,11 @@ def _load_std_objs(
"""Load the standard objects."""

with open(file_path, "r") as f:
std_objs_raw = load(f, Loader=Loader)
std_objs_raw = load(f, Loader=CLoader)

std_objs = {}
for obj_raw in std_objs_raw:
obj = IndexObject.from_dict(obj_raw) # pylint: disable=E1101
obj = from_dict(data_class=IndexObject, data=obj_raw)
if obj.object_type == "variable":
std_objs[obj.name] = _make_var(obj, obj.index)
elif obj.object_type == "record":
Expand Down
18 changes: 4 additions & 14 deletions oresat_configs/beacon_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,11 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from yaml import load
from dacite import from_dict
from yaml import CLoader, load

Loader: Any
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader

from dataclasses_json import dataclass_json


@dataclass_json
@dataclass
class BeaconAx25Config:
"""
Expand Down Expand Up @@ -55,7 +46,6 @@ class BeaconAx25Config:
"""If set to True, the C-bit in source field."""


@dataclass_json
@dataclass
class BeaconConfig:
"""
Expand Down Expand Up @@ -94,5 +84,5 @@ def from_yaml(cls, config_path: str) -> BeaconConfig:
"""Load a beacon YAML config file."""

with open(config_path, "r") as f:
config_raw = load(f, Loader=Loader)
return cls.from_dict(config_raw) # type: ignore # pylint: disable=E1101
config_raw = load(f, Loader=CLoader)
return from_dict(data_class=cls, data=config_raw)
24 changes: 6 additions & 18 deletions oresat_configs/card_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,13 @@
from __future__ import annotations

from dataclasses import dataclass, field
from functools import cache
from typing import Any, Optional, Union

from yaml import load
from dacite import from_dict
from yaml import CLoader, load

Loader: Any
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader

from dataclasses_json import dataclass_json


@dataclass_json
@dataclass
class ConfigObject:
"""Object in config."""
Expand Down Expand Up @@ -52,7 +45,6 @@ class ConfigObject:
"""


@dataclass_json
@dataclass
class GenerateSubindex(ConfigObject):
"""
Expand Down Expand Up @@ -81,7 +73,6 @@ class GenerateSubindex(ConfigObject):
"""Subindexes of objects to generate."""


@dataclass_json
@dataclass
class SubindexObject(ConfigObject):
"""
Expand All @@ -107,7 +98,6 @@ class SubindexObject(ConfigObject):
"""


@dataclass_json
@dataclass
class IndexObject(ConfigObject):
"""
Expand Down Expand Up @@ -137,7 +127,6 @@ class IndexObject(ConfigObject):
"""Used to generate subindexes for arrays."""


@dataclass_json
@dataclass
class Tpdo:
"""
Expand Down Expand Up @@ -176,7 +165,6 @@ class Tpdo:
"""Index and subindexes of objects to map to the TPDO."""


@dataclass_json
@dataclass
class Rpdo:
"""
Expand All @@ -200,7 +188,6 @@ class Rpdo:
"""TPDO number, 1-16."""


@dataclass_json
@dataclass
class CardConfig:
"""
Expand Down Expand Up @@ -245,9 +232,10 @@ class CardConfig:
"""C3 only. List of index and subindex for the c3 to save the values of to F-RAM."""

@classmethod
@cache
def from_yaml(cls, config_path: str) -> CardConfig:
"""Load a card YAML config file."""

with open(config_path, "r") as f:
config_raw = load(f, Loader=Loader)
return cls.from_dict(config_raw) # type: ignore # pylint: disable=E1101
config_raw = load(f, Loader=CLoader)
return from_dict(data_class=cls, data=config_raw)
3 changes: 0 additions & 3 deletions oresat_configs/card_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@
import os
from dataclasses import dataclass, fields

from dataclasses_json import dataclass_json

from .constants import Consts


@dataclass_json
@dataclass
class Card:
"""Card info."""
Expand Down
8 changes: 3 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,19 @@ build-backend = "setuptools.build_meta"
name = "oresat-configs"
description = "OreSat mission configurations"
readme = "README.md"
requires-python = ">=3.7"
requires-python = ">=3.9"
license = {text = "GPL-3.0"}
classifiers = [
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
dependencies = [
"canopen",
"dataclasses-json",
"dacite",
"pyyaml",
]
dynamic = ["version"]
Expand All @@ -47,7 +45,7 @@ line_length = 100

[tool.pylama]
format = "pylint"
skip = "*/.tox/*,*/.env/,*/.git/*,*/.github/*,*/build/*"
skip = "*/.tox/*,*/.env/,*/.git/*,*/.github/*,*/build/*,.direnv/*"
linters = "pycodestyle,pyflakes,pylint,mccabe,mypy,radon"
# E402: Module level import not at top of file
# C901: Function is too complex
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ black
build
canopen
dacite
dataclasses-json
isort
pylama[all]
pylama[toml]
Expand Down

0 comments on commit e250690

Please sign in to comment.