Source code for waves.utilities.library

"""Provides a consistent way to read and write YAML data, largely based on WOMBAT's
library module.

All library data should adhere to the following directory structure within a library path:

::

  ├── project
    ├── config     <- Project-level configuration files
    ├── port       <- Port configuration files
    ├── plant      <- Wind farm layout files
  ├── cables       <- Export and Array cable configuration files
  ├── substations  <- Substation configuration files
  ├── turbines     <- Turbine configuration and power curve files
  ├── vessels      <- Land-based and offshore servicing equipment configuration files
  ├── weather      <- Weather profiles
  ├── results      <- The analysis log files and any saved output data
"""

from __future__ import annotations

import re
from typing import Any
from pathlib import Path

import yaml


# YAML SafeLoader that is able to read scientific notation and Python Tuples
[docs] class CustomSafeLoader(yaml.SafeLoader): """Customized ``yaml.SafeLoader`` that adds custom constructors for consistent data loading in safe mode. """
[docs] def construct_python_tuple(self, node): """Loads a YAML object to a Pytho Tuple.s.""" return tuple(self.construct_sequence(node))
custom_loader = yaml.SafeLoader custom_loader.add_implicit_resolver( "tag:yaml.org,2002:float", re.compile( """^(?: [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)? |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+) |\\.[0-9_]+(?:[eE][-+][0-9]+)? |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]* |[-+]?\\.(?:inf|Inf|INF) |\\.(?:nan|NaN|NAN))$""", re.X, ), list("-+0123456789."), ) custom_loader.add_constructor( "tag:yaml.org,2002:python/tuple", CustomSafeLoader.construct_python_tuple )
[docs] def resolve_path(value: str | Path) -> Path: """Converts a user-input string to a ``Path`` object and resolves it. Parameters ---------- value : str | Path A string or Path to a configuration library. Raises ------ TypeError: Raised if the input to :py:attr:`value` is not either a ``str`` or ``pathlib.Path``. Returns ------- Path The resolved Path object version of the input library path. """ if isinstance(value, str): value = Path(value) if isinstance(value, Path): return value.resolve() raise TypeError(f"The input path: {value}, must be of type `str` or `pathlib.Path`.")
[docs] def load_yaml(path: str | Path, fname: str | Path) -> Any: """Loads and returns the contents of the YAML file. Parameters ---------- path : str | Path Path to the file to be loaded. fname : str | Path Name of the file (ending in .yaml) to be loaded. Returns ------- Any Whatever content is in the YAML file. """ path = Path(path).resolve() return yaml.load(open(path / fname), Loader=custom_loader)