Configuration & Validation

Configuration schemas and validation for cruise planning YAML files.

Configuration and validation module for cruise planning.

This module provides configuration schemas and validation for cruise planning YAML files. Import classes directly from submodules for explicit dependencies:

Examples

from cruiseplan.config.activities import PointDefinition, AreaDefinition, LineDefinition from cruiseplan.config.cruise_config import CruiseConfig, LegDefinition, ClusterDefinition from cruiseplan.config.exceptions import ValidationError, BathymetryError, FileError from cruiseplan.config.fields import POINTS_FIELD, LEGS_FIELD, ACTION_FIELD from cruiseplan.config.values import OperationTypeEnum, ActionEnum, StrategyEnum from cruiseplan.config.ports import resolve_port_reference, get_available_ports

cruiseplan.config.activities module

Schema definitions for cruise configuration operations.

Defines Pydantic models that validate and parse YAML configuration data for points, lines, and areas. These are the “schema layer” that ensures your YAML is structured correctly.

Relationship to core/operations.py: - This module: Pydantic models that validate YAML → Python data - core/operations.py: Runtime business objects that do the actual work

Example flow: YAML → PointDefinition (this module) → PointOperation (core)

Also includes base geographic models used throughout the validation system.

class cruiseplan.config.activities.AreaDefinition(*, name: str, corners: list[GeoPoint], comment: str | None = None, operation_type: AreaOperationTypeEnum | None = AreaOperationTypeEnum.SURVEY, action: ActionEnum | None = None, duration: float | None = None)[source]

Bases: BaseModel

Definition of an area for survey operations.

Represents a polygonal region for area-based scientific operations such as bathymetric surveys or habitat mapping.

name

Unique identifier for the area.

Type:

str

corners

List of corner points defining the area boundary.

Type:

List[GeoPoint]

comment

Human-readable comment or description.

Type:

Optional[str]

operation_type

Type of operation for the area (default: “survey”).

Type:

Optional[AreaOperationTypeEnum]

action

Specific action for the area operation.

Type:

Optional[ActionEnum]

duration

Duration for the area operation in minutes.

Type:

Optional[float]

action: ActionEnum | None
comment: str | None
corners: list[GeoPoint]
duration: float | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
operation_type: AreaOperationTypeEnum | None
classmethod validate_corners_minimum(v)[source]

Validate at least 3 corners for a valid area.

classmethod validate_duration(v)[source]

Validate duration is positive.

class cruiseplan.config.activities.FlexibleLocationModel(*, latitude: float | None = None, longitude: float | None = None)[source]

Bases: BaseModel

Base class that allows users to define location in multiple formats.

Supports both explicit latitude/longitude fields and string format (“lat, lon”) in YAML input for user convenience.

latitude

Latitude in decimal degrees.

Type:

Optional[float]

longitude

Longitude in decimal degrees.

Type:

Optional[float]

latitude: float | None
longitude: float | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod unify_coordinates(data: Any) Any[source]

Unify different coordinate input formats.

Handles both explicit lat/lon fields and string position format.

Parameters:

data (Any) – Input data dictionary to process.

Returns:

Processed data with latitude and longitude fields.

Return type:

Any

Raises:

ValueError – If position string cannot be parsed as “lat, lon”.

class cruiseplan.config.activities.GeoPoint(*, latitude: float, longitude: float)[source]

Bases: BaseModel

Internal representation of a geographic point.

Represents a latitude/longitude coordinate pair with validation.

latitude

Latitude in decimal degrees (-90 to 90).

Type:

float

longitude

Longitude in decimal degrees (-180 to 360).

Type:

float

latitude: float
longitude: float
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod validate_lat(v)[source]

Validate latitude using centralized coordinate utilities.

classmethod validate_lon(v)[source]

Validate longitude using centralized coordinate utilities.

class cruiseplan.config.activities.LineDefinition(*, name: str, route: list[GeoPoint], comment: str | None = None, vessel_speed: float | None = None, operation_type: LineOperationTypeEnum | None = None, action: ActionEnum | None = None, distance_between_stations: float | None = None, max_depth: float | None = None)[source]

Bases: BaseModel

Definition of a transect route for line operations.

Represents a planned path between geographic points for scientific operations such as ADCP surveys, CTD sections, or towed instruments. Uses oceanographically correct terminology where “transect” refers to the spatial sampling path/route.

name

Unique identifier for the transect.

Type:

str

route

List of waypoints defining the transect route.

Type:

List[GeoPoint]

comment

Human-readable comment or description.

Type:

Optional[str]

vessel_speed

Speed for this transect in knots.

Type:

Optional[float]

operation_type

Type of operation for scientific transects.

Type:

Optional[LineOperationTypeEnum]

action

Specific action for scientific transects.

Type:

Optional[ActionEnum]

action: ActionEnum | None
comment: str | None
distance_between_stations: float | None
max_depth: float | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
operation_type: LineOperationTypeEnum | None
classmethod parse_route_strings(v)[source]

Parse route strings into GeoPoint objects.

Parameters:

v (List[Union[str, dict]]) – List of route points as strings or dictionaries.

Returns:

List of parsed route points.

Return type:

List[dict]

route: list[GeoPoint]
classmethod validate_vessel_speed(v)[source]

Validate vessel speed is positive.

vessel_speed: float | None
class cruiseplan.config.activities.PointDefinition(*, latitude: float | None = None, longitude: float | None = None, name: str, operation_type: OperationTypeEnum | None = None, action: ActionEnum | None = None, operation_depth: float | None = None, water_depth: float | None = None, duration: float | None = None, delay_start: float | None = None, delay_end: float | None = None, comment: str | None = None, equipment: str | None = None, position_string: str | None = None, display_name: str | None = None, timezone: str | None = None)[source]

Bases: FlexibleLocationModel

Definition of a waypoint location with operation details.

Unified definition for all point operations including CTD stations, moorings, ports, and navigation waypoints. Represents a specific geographic point where operations will be performed.

name

Unique identifier for the waypoint.

Type:

str

operation_type

Type of scientific operation to perform.

Type:

OperationTypeEnum

action

Specific action for the operation.

Type:

ActionEnum

operation_depth

Target operation depth (e.g., CTD cast depth) in meters.

Type:

Optional[float]

water_depth

Water depth at location (seafloor depth) in meters.

Type:

Optional[float]

duration

Manual duration override in minutes.

Type:

Optional[float]

delay_start

Time to wait before operation begins in minutes (e.g., for daylight).

Type:

Optional[float]

delay_end

Time to wait after operation ends in minutes (e.g., for equipment settling).

Type:

Optional[float]

comment

Human-readable comment or description.

Type:

Optional[str]

equipment

Equipment required for the operation.

Type:

Optional[str]

position_string

Original position string for reference.

Type:

Optional[str]

display_name

Human-readable display name (for ports).

Type:

Optional[str]

timezone

Timezone identifier (for ports).

Type:

Optional[str]

action: ActionEnum | None
comment: str | None
delay_end: float | None
delay_start: float | None
display_name: str | None
duration: float | None
equipment: str | None
get_ddm_comment() str[source]

Generate DDM (Degree Decimal Minutes) position comment.

Returns:

Position in DDM format for display.

Return type:

str

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
classmethod normalize_operation_type(v)[source]

Normalize operation_type for case-insensitive validation.

operation_depth: float | None
operation_type: OperationTypeEnum | None
position_string: str | None
timezone: str | None
classmethod validate_operation_depth(v)[source]

Validate operation depth is positive.

classmethod validate_water_depth(v)[source]

Validate water depth is positive.

water_depth: float | None

cruiseplan.config.cruise_config module

Main cruise configuration and schedule organization models.

Defines the root CruiseConfig class and schedule organization models (LegDefinition, ClusterDefinition) that represent the complete cruise configuration file. This is the top-level YAML structure that contains all cruise metadata, global catalog definitions, and schedule organization.

class cruiseplan.config.cruise_config.ClusterDefinition(*, name: str, description: str | None = None, strategy: StrategyEnum = StrategyEnum.SEQUENTIAL, ordered: bool = True, activities: list[str | dict[str, ~typing.Any]]=<factory>, **extra_data: Any)[source]

Bases: BaseModel

Definition of a cluster for operation boundary management.

Clusters define boundaries for operation shuffling/reordering during scheduling. Operations within a cluster can be reordered according to the cluster’s strategy, but cannot be mixed with operations from other clusters or the parent leg.

name

Unique identifier for the cluster.

Type:

str

description

Human-readable description of the cluster purpose.

Type:

Optional[str]

strategy

Scheduling strategy for the cluster (default: SEQUENTIAL).

Type:

StrategyEnum

ordered

Whether operations should maintain their order (default: True).

Type:

bool

activities

Unified list of all activities (stations, transits, areas) in this cluster.

Type:

List[dict]

activities: list[str | dict[str, Any]]
description: str | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
ordered: bool
strategy: StrategyEnum
validate_cluster_activities()[source]

Validate cluster has activities and handle deprecated fields.

Returns:

Validated cluster definition.

Return type:

ClusterDefinition

Raises:

ValueError – If cluster has no activities defined.

classmethod validate_strategy(v)[source]

Ensure strategy is a valid StrategyEnum.

class cruiseplan.config.cruise_config.CruiseConfig(*, cruise_name: str, description: str | None = None, default_vessel_speed: float = 10.0, default_distance_between_stations: float = 15.0, turnaround_time: float = 30.0, ctd_descent_rate: float = 1.0, ctd_ascent_rate: float = 1.0, day_start_hour: int = 8, day_end_hour: int = 20, start_date: str = '1970-01-01T00:00:00+00:00', start_time: str | None = '08:00', departure_port: str | PointDefinition | None = None, arrival_port: str | PointDefinition | None = None, points: list[PointDefinition] | None = <factory>, lines: list[LineDefinition] | None = <factory>, areas: list[AreaDefinition] | None = <factory>, ports: list[PointDefinition] | None = <factory>, legs: list[LegDefinition] | None = <factory>, **extra_data: Any)[source]

Bases: BaseModel

Root configuration model for cruise planning.

Contains all the high-level parameters and definitions for a complete oceanographic cruise plan. Represents the top-level YAML structure with cruise metadata, global catalog, and schedule organization.

cruise_name

Name of the cruise.

Type:

str

description

Human-readable description of the cruise.

Type:

Optional[str]

default_vessel_speed

Default vessel speed in knots.

Type:

float

default_distance_between_stations

Default station spacing in kilometers.

Type:

float

turnaround_time

Time required for station turnaround in minutes.

Type:

float

ctd_descent_rate

CTD descent rate in meters per second.

Type:

float

ctd_ascent_rate

CTD ascent rate in meters per second.

Type:

float

day_start_hour

Start hour for daytime operations (0-23).

Type:

int

day_end_hour

End hour for daytime operations (0-23).

Type:

int

start_date

Cruise start date.

Type:

str

start_time

Cruise start time.

Type:

Optional[str]

departure_port

Port where the cruise begins.

Type:

Optional[Union[str, PointDefinition]]

arrival_port

Port where the cruise ends.

Type:

Optional[Union[str, PointDefinition]]

points

Global catalog of point definitions.

Type:

Optional[List[PointDefinition]]

lines

Global catalog of line definitions.

Type:

Optional[List[LineDefinition]]

areas

Global catalog of area definitions.

Type:

Optional[List[AreaDefinition]]

ports

Global catalog of port definitions.

Type:

Optional[List[WaypointDefinition]]

legs

List of cruise legs for schedule organization.

Type:

Optional[List[LegDefinition]]

areas: list[AreaDefinition] | None
arrival_port: str | PointDefinition | None
cruise_name: str
ctd_ascent_rate: float
ctd_descent_rate: float
day_end_hour: int
day_start_hour: int
default_distance_between_stations: float
default_vessel_speed: float
departure_port: str | PointDefinition | None
description: str | None
legs: list[LegDefinition] | None
lines: list[LineDefinition] | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

points: list[PointDefinition] | None
ports: list[PointDefinition] | None
start_date: str
start_time: str | None
turnaround_time: float
validate_cruise_structure()[source]

Validate overall cruise configuration structure.

Returns:

Validated cruise configuration.

Return type:

CruiseConfig

Raises:

ValueError – If cruise structure is invalid.

class cruiseplan.config.cruise_config.LegDefinition(*, name: str, description: str | None = None, departure_port: str | PointDefinition, arrival_port: str | PointDefinition, vessel_speed: float | None = None, distance_between_stations: float | None = None, turnaround_time: float | None = None, first_activity: str | None = None, last_activity: str | None = None, strategy: StrategyEnum | None = None, ordered: bool | None = None, buffer_time: float | None = None, activities: list[str | dict[str, ~typing.Any]] | None=<factory>, clusters: list[ClusterDefinition] | None = <factory>, **extra_data: Any)[source]

Bases: BaseModel

Definition of a maritime cruise leg (port-to-port segment).

Represents a complete leg of the cruise from departure port to arrival port, containing all operations and clusters that occur during this segment. Maritime legs are always port-to-port with defined departure and arrival points.

name

Unique identifier for the leg.

Type:

str

description

Human-readable description of the leg.

Type:

Optional[str]

departure_port

Required departure port for this leg.

Type:

Union[str, PointDefinition]

arrival_port

Required arrival port for this leg.

Type:

Union[str, PointDefinition]

vessel_speed

Vessel speed for this leg in knots (inheritable from cruise).

Type:

Optional[float]

distance_between_stations

Default station spacing for this leg in kilometers (inheritable from cruise).

Type:

Optional[float]

turnaround_time

Turnaround time between operations in minutes (inheritable from cruise).

Type:

Optional[float]

first_activity

First activity/navigation marker for this leg (routing only, not executed).

Type:

Optional[str]

last_activity

Last activity/navigation marker for this leg (routing only, not executed).

Type:

Optional[str]

strategy

Default scheduling strategy for the leg.

Type:

Optional[StrategyEnum]

ordered

Whether the leg operations should be ordered.

Type:

Optional[bool]

buffer_time

Contingency time for entire leg operations in minutes (e.g., weather delays).

Type:

Optional[float]

activities

Unified list of all activities (points, lines, areas) in this leg.

Type:

Optional[List[dict]]

clusters

List of operation clusters in the leg.

Type:

Optional[List[ClusterDefinition]]

activities: list[str | dict[str, Any]] | None
arrival_port: str | PointDefinition
buffer_time: float | None
clusters: list[ClusterDefinition] | None
departure_port: str | PointDefinition
description: str | None
distance_between_stations: float | None
first_activity: str | None
last_activity: str | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
ordered: bool | None
strategy: StrategyEnum | None
turnaround_time: float | None
validate_leg_structure()[source]

Validate leg has valid structure and content.

Returns:

Validated leg definition.

Return type:

LegDefinition

Raises:

ValueError – If leg structure is invalid.

classmethod validate_ports(v)[source]

Validate port references are not None.

classmethod validate_station_spacing(v)[source]

Validate station spacing is positive.

classmethod validate_time_fields(v)[source]

Validate time fields are non-negative.

classmethod validate_vessel_speed(v)[source]

Validate vessel speed is positive.

vessel_speed: float | None

cruiseplan.config.exceptions module

Custom exception types for CruisePlan.

Provides clean error handling for configuration validation, file operations, and bathymetry processing.

exception cruiseplan.config.exceptions.BathymetryError[source]

Bases: Exception

Raised when bathymetry operations fail.

exception cruiseplan.config.exceptions.FileError[source]

Bases: Exception

Raised when file operations fail (reading, writing, permissions).

exception cruiseplan.config.exceptions.ValidationError[source]

Bases: Exception

Raised when configuration validation fails.

cruiseplan.config.fields module

YAML field name constants for cruise configuration schema.

Centralized field name constants to enable easy renaming across the codebase. This module focuses on the structural field names (left-hand side of YAML), while cruiseplan.schema.values focuses on field values (right-hand side of YAML).

Note: New field constants need to be added above and in the __all__ list at the bottom.

cruiseplan.config.ports module

Global port configuration system for maritime cruise planning.

This module provides a registry of common maritime ports with their coordinates, timezones, and metadata. Users can reference these ports by standard identifiers (e.g., ‘port_reykjavik’) or override them with custom definitions in their YAML.

Features: - Standard port registry with common research cruise destinations - Timezone information for port operations - Extensible system allowing user-defined port overrides - Support for both string references and PointDefinition objects

Usage:

# In YAML configuration departure_port: “port_reykjavik” # Reference to global port

# Or override with custom definition departure_port:

name: “Reykjavik_Custom” latitude: 64.1466 longitude: -21.9426 timezone: “GMT+0” comment: “Custom port definition”

cruiseplan.config.ports.add_custom_port(port_id: str, port_data: dict[str, Any]) None[source]

Add a custom port to the global registry at runtime.

Useful for adding project-specific ports that aren’t in the default registry.

Parameters:
  • port_id (str) – Port identifier (should start with ‘port_’).

  • port_data (dict) – Port data dictionary with required fields (name, latitude, longitude).

Raises:

ValueError – If port_id doesn’t follow naming convention or required fields are missing.

cruiseplan.config.ports.get_available_ports() dict[str, str][source]

Get a dictionary of available global ports with comments.

Returns:

Mapping of port identifiers to comments.

Return type:

Dict[str, str]

cruiseplan.config.ports.list_ports_in_region(min_lat: float, max_lat: float, min_lon: float, max_lon: float) dict[str, str][source]

List ports within a geographic bounding box.

Parameters:
  • min_lat (float) – Latitude bounds in degrees.

  • max_lat (float) – Latitude bounds in degrees.

  • min_lon (float) – Longitude bounds in degrees.

  • max_lon (float) – Longitude bounds in degrees.

Returns:

Mapping of port identifiers to names for ports in the region.

Return type:

Dict[str, str]

cruiseplan.config.ports.resolve_port_reference(port_ref: str | dict[str, Any] | object, port_catalog: dict[str, Any] | None = None) object[source]

Resolve a port reference to a complete PointDefinition object.

Handles three types of input: 1. String reference to local catalog or global port registry (e.g., ‘port_reykjavik’) 2. Dictionary with port data (user-defined override) 3. Already instantiated PointDefinition object

Parameters:
  • port_ref – Port reference to resolve.

  • port_catalog (dict, optional) – Local port catalog to check first before falling back to global registry. Should be a dict mapping port names to PointDefinition objects or dicts.

Returns:

Complete port definition object.

Return type:

PointDefinition

Raises:

ValueError – If string reference is not found in catalog or global registry.

cruiseplan.config.values module

YAML field values and enumeration types for cruise configuration.

This module defines valid values that can appear in YAML configuration fields (right-hand side of YAML), along with their defaults. This complements cruiseplan.schema.fields which defines field names (left-hand side of YAML).

Contains: - Default value constants for YAML fields - Placeholder values for user guidance - Enumeration classes for valid field values

class cruiseplan.config.values.ActionEnum(*values)[source]

Bases: str, Enum

Enumeration of specific actions for operations.

Defines the specific scientific action to be taken for each operation type.

ADCP = 'ADCP'
BATHYMETRY = 'bathymetry'
CALIBRATION = 'calibration'
DEFAULT_AREA = 'UPDATE-bathymetry-survey-etc'
DEFAULT_LINE = 'UPDATE-ADCP-bathymetry-etc'
DEFAULT_POINT = 'UPDATE-profile-sampling-etc'
DEMOB = 'demob'
DEPLOYMENT = 'deployment'
MICROSTRUCTURE = 'microstructure'
MOB = 'mob'
PROFILE = 'profile'
RECOVERY = 'recovery'
SAMPLING = 'sampling'
SECTION = 'section'
SEISMIC = 'seismic'
THERMOSALINOGRAPH = 'thermosalinograph'
TOW_YO = 'tow_yo'
class cruiseplan.config.values.AreaOperationTypeEnum(*values)[source]

Bases: str, Enum

Enumeration of area operation types.

Defines operations that cover defined geographic areas.

DEFAULT = 'UPDATE-survey-etc'
SURVEY = 'survey'
class cruiseplan.config.values.LineOperationTypeEnum(*values)[source]

Bases: str, Enum

Enumeration of line operation types.

Defines the type of operation performed along a route or transect.

CTD = 'CTD'
DEFAULT = 'UPDATE-underway-etc'
TOWING = 'towing'
UNDERWAY = 'underway'
class cruiseplan.config.values.OperationTypeEnum(*values)[source]

Bases: str, Enum

Enumeration of point operation types.

Defines the type of scientific operation to be performed at a station.

CALIBRATION = 'calibration'
CTD = 'CTD'
DEFAULT = 'UPDATE-CTD-mooring-etc'
MOORING = 'mooring'
PORT = 'port'
WATER_SAMPLING = 'water_sampling'
WAYPOINT = 'waypoint'
class cruiseplan.config.values.StrategyEnum(*values)[source]

Bases: str, Enum

Enumeration of scheduling strategies for cruise operations.

Defines how operations within a cluster or composite should be executed.

DAY_NIGHT_SPLIT = 'day_night_split'
SEQUENTIAL = 'sequential'
SPATIAL_INTERLEAVED = 'spatial_interleaved'

cruiseplan.config.yaml_io module

Centralized YAML I/O utilities with comment preservation.

This module provides middle-layer YAML file format handling for the cruiseplan package, using ruamel.yaml to preserve comments, formatting, and whitespace during configuration enrichment operations.

I/O Module Architecture: - cruiseplan.utils.io: File system validation, path handling, directory creation (used by this module) - cruiseplan.schema.yaml_io (this module): YAML file format reading/writing with comment preservation - cruiseplan.core.serialization: High-level CruiseInstance object serialization to YAML (uses this module) - cruiseplan.output.*_generator: Specialized output format generators (HTML, LaTeX, CSV, etc.)

Dependencies: Uses cruiseplan.utils.io for file validation. Used by cruiseplan.core.serialization.

See Also: - For file system operations: cruiseplan.utils.io - For converting CruiseInstance objects to YAML: cruiseplan.core.serialization - For generating specific output formats: cruiseplan.output.html_generator, cruiseplan.output.latex_generator, etc.

exception cruiseplan.config.yaml_io.YAMLIOError[source]

Bases: Exception

Custom exception for YAML I/O operations.

cruiseplan.config.yaml_io.dict_to_yaml_string(data: dict[str, Any], add_comments: bool = True) str[source]

Convert dictionary to YAML string with optional section comments.

Parameters:
  • data (dict[str, Any]) – Dictionary to convert to YAML

  • add_comments (bool, optional) – Whether to add section comments (default: True)

Returns:

YAML string with optional comments and spacing

Return type:

str

cruiseplan.config.yaml_io.dump_yaml_simple(data: dict[str, Any], file_handle: TextIO) None[source]

Dump YAML data to file handle without comment preservation.

This function provides basic YAML dumping for cases like temp files where comment preservation is not needed.

Args:

data: Dictionary to dump file_handle: Open file handle to write to

Raises:

YAMLIOError – If dumping fails:

cruiseplan.config.yaml_io.load_yaml(file_path: str | Path, encoding: str = 'utf-8') dict[str, Any][source]

Load YAML configuration file with comment preservation.

Args:

file_path: Path to YAML file encoding: File encoding

Return type:

Parsed YAML content as dictionary

Raises:

YAMLIOError – If file cannot be loaded or parsed:

cruiseplan.config.yaml_io.load_yaml_safe(file_path: str | Path) dict[str, Any][source]

Load YAML file using ruamel.yaml safe loading (returns plain dict).

This function provides basic dictionary loading without comment preservation. Returns a plain Python dictionary instead of ruamel.yaml’s CommentedMap. Use load_yaml() for comment-preserving operations.

Args:

file_path: Path to YAML file

Return type:

Parsed YAML content as basic dictionary

Raises:

YAMLIOError – If file cannot be loaded or parsed:

cruiseplan.config.yaml_io.save_yaml(config: dict[str, Any], file_path: str | Path, backup: bool = False, encoding: str = 'utf-8') None[source]

Save configuration to YAML file with comment preservation.

Args:

config: Configuration dictionary to save file_path: Output file path backup: Whether to create backup of existing file encoding: File encoding

Raises:

YAMLIOError – If file cannot be written: