Skip to content

Commit

Permalink
✨ Use ruaml.yaml parser for roundtrip support (#893)
Browse files Browse the repository at this point in the history
* ✨ Replaced pyyaml with ruaml.yaml

* 👌 Set yaml repr for None to null, instead of missing value ('')

* 👌 Changed list element indentation to be consistent with current style

* 🧹 Sorted dependencies in requirements_dev.txt same as setup.cfg

This way it is easier to compare them and see discrepancies
  • Loading branch information
s-weigand authored Nov 11, 2021
1 parent efc333a commit 8ae1b90
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 48 deletions.
55 changes: 28 additions & 27 deletions glotaran/builtin/io/yml/test/test_save_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,49 @@
from pathlib import Path


want = """dataset:
dataset1:
group: default
initial_concentration: j1
irf: irf1
megacomplex:
- m1
want = """\
default_megacomplex: decay
dataset_groups:
default:
link_clp: null
residual_function: variable_projection
default_megacomplex: decay
link_clp: null
k_matrix:
k1:
matrix:
(s2, s1): kinetic.1
(s3, s2): kinetic.2
(s3, s3): kinetic.3
initial_concentration:
j1:
compartments:
- s1
- s2
- s3
exclude_from_normalize: []
- s1
- s2
- s3
parameters:
- j.1
- j.0
- j.0
- j.1
- j.0
- j.0
exclude_from_normalize: []
irf:
irf1:
backsweep: false
center: irf.center
normalize: true
type: gaussian
center: irf.center
width: irf.width
k_matrix:
k1:
matrix:
(s2, s1): kinetic.1
(s3, s2): kinetic.2
(s3, s3): kinetic.3
normalize: true
backsweep: false
megacomplex:
m1:
type: decay
dimension: time
k_matrix:
- k1
type: decay
- k1
dataset:
dataset1:
group: default
megacomplex:
- m1
initial_concentration: j1
irf: irf1
"""


Expand Down
15 changes: 8 additions & 7 deletions glotaran/builtin/io/yml/test/test_save_scheme.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@
from pathlib import Path


want = """add_svd: true
clp_link_tolerance: 0.0
want = """\
model_file: m.yml
parameters_file: p.csv
data_files:
dataset_1: d.nc
ftol: 1.0e-08
gtol: 1.0e-08
clp_link_tolerance: 0.0
maximum_number_function_evaluations: null
model_file: m.yml
add_svd: true
ftol: 1e-08
gtol: 1e-08
xtol: 1e-08
optimization_method: TrustRegionReflection
parameters_file: p.csv
result_path: null
xtol: 1.0e-08
"""


Expand Down
44 changes: 39 additions & 5 deletions glotaran/builtin/io/yml/yml.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

import yaml
from ruamel.yaml import YAML

from glotaran.deprecation.modules.builtin_io_yml import model_spec_deprecations
from glotaran.deprecation.modules.builtin_io_yml import scheme_spec_deprecations
Expand All @@ -17,6 +18,13 @@
from glotaran.project.dataclass_helpers import fromdict
from glotaran.utils.sanitize import sanitize_yaml

if TYPE_CHECKING:
from typing import Any
from typing import Mapping

from ruamel.yaml.nodes import ScalarNode
from ruamel.yaml.representer import BaseRepresenter


@register_project_io(["yml", "yaml", "yml_str"])
class YmlProjectIo(ProjectIoInterface):
Expand Down Expand Up @@ -137,14 +145,40 @@ def save_result(self, result: Result, result_path: str):
_write_dict(result_path, result_dict)

def _load_yml(self, file_name: str) -> dict:
yaml = YAML()
if self.format == "yml_str":
spec = yaml.safe_load(file_name)
spec = yaml.load(file_name)
else:
with open(file_name) as f:
spec = yaml.safe_load(f)
spec = yaml.load(f)
return spec


def _write_dict(file_name: str, d: dict):
def _write_dict(file_name: str, data: Mapping[str, Any]):
yaml = YAML()
yaml.representer.add_representer(type(None), _yaml_none_representer)
yaml.indent(mapping=2, sequence=2, offset=2)
with open(file_name, "w") as f:
f.write(yaml.dump(d))
yaml.dump(data, f)


def _yaml_none_representer(representer: BaseRepresenter, data: Mapping[str, Any]) -> ScalarNode:
"""Yaml repr for ``None`` python values.
Parameters
----------
representer : BaseRepresenter
Representer of the :class:`YAML` instance.
data : Mapping[str, Any]
Data to write to yaml.
Returns
-------
ScalarNode
Node representing the value.
References
----------
https://stackoverflow.com/a/44314840
"""
return representer.represent_scalar("tag:yaml.org,2002:null", "null")
16 changes: 8 additions & 8 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ wheel>=0.30.0

# glotaran setup dependencies
asteval==0.9.25
numpy==1.20.3
scipy==1.7.1
click==8.0.3
rich==10.12.0
netCDF4==1.5.7
numba==0.54.1
numpy==1.20.3
pandas==1.3.4
pyyaml==6.0
xarray==0.19.0
netCDF4==1.5.7
setuptools==41.2
rich==10.12.0
ruamel.yaml==0.17.17
scipy==1.7.1
sdtfile==2021.3.21
typing_inspect==0.7.1
setuptools==41.2
tabulate==0.8.9
typing_inspect==0.7.1
xarray==0.19.0

# documentation dependencies
-r docs/requirements.txt
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ install_requires =
numba>=0.52
numpy>=1.20.0,<1.21
pandas>=0.25.2
pyyaml>=5.2
rich>=10.9.0
ruamel.yaml>=0.17.17
scipy>=1.3.2
sdtfile>=2020.8.3
setuptools>=41.2
Expand Down

0 comments on commit 8ae1b90

Please sign in to comment.