Source code for eodag.utils.yaml

# -*- coding: utf-8 -*-
# Copyright 2026, CS GROUP - France, https://www.csgroup.eu/
#
# This file is part of EODAG project
#     https://www.github.com/CS-SI/EODAG
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

import functools
import os
import warnings
from copy import deepcopy as copy_deepcopy
from typing import Any

import yaml


[docs] class LegacyAwareLoader(yaml.CSafeLoader): """YAML loader that accepts legacy EODAG tags (!provider, !plugin, !!python/tuple) and converts them to safe Python objects. Uses CSafeLoader for performance."""
# Constructor for !provider tag - reuse legacy deserialization logic # from ProviderConfig and keep deprecation warnings. def provider_constructor(loader, node): if isinstance(node, yaml.MappingNode): from eodag.api.provider import ProviderConfig warnings.warn( "Usage of deprecated YAML tag '!provider' for provider configuration " "(Please use plain YAML mappings instead)" " -- Deprecated since v4.5.0", FutureWarning, stacklevel=2, ) return ProviderConfig.from_yaml(loader, node) return None # Constructor for !plugin tag - reuse legacy deserialization logic. def plugin_constructor(loader, node): if isinstance(node, yaml.MappingNode): from eodag.config import PluginConfig warnings.warn( "Usage of deprecated YAML tag '!plugin' for plugin configuration " "(Please use plain YAML mappings instead)" " -- Deprecated since v4.5.0", FutureWarning, stacklevel=2, ) return PluginConfig.from_yaml(loader, node) return None # Constructor for !!python/tuple tag - convert to tuple. def python_tuple_constructor(loader, node): if isinstance(node, yaml.SequenceNode): return tuple(loader.construct_sequence(node)) elif isinstance(node, yaml.ScalarNode): return (loader.construct_scalar(node),) return None # Register constructors for legacy tags. LegacyAwareLoader.add_constructor("!provider", provider_constructor) LegacyAwareLoader.add_constructor("!plugin", plugin_constructor) LegacyAwareLoader.add_constructor( "tag:yaml.org,2002:python/tuple", python_tuple_constructor ) @functools.lru_cache() def _mutable_cached_yaml_load(config_path: str) -> Any: with open( os.path.abspath(os.path.realpath(config_path)), mode="r", encoding="utf-8" ) as fh: return yaml.load(fh, Loader=LegacyAwareLoader)
[docs] def cached_yaml_load(config_path: str) -> dict[str, Any]: """Cached :func:`yaml.load` :param config_path: path to the yaml configuration file :returns: loaded yaml configuration """ return copy_deepcopy(_mutable_cached_yaml_load(config_path))
@functools.lru_cache() def _mutable_cached_yaml_load_all(config_path: str) -> list[Any]: with open(config_path, "r") as fh: return list(yaml.load_all(fh, Loader=LegacyAwareLoader))
[docs] def cached_yaml_load_all(config_path: str) -> list[Any]: """Cached :func:`yaml.load_all` Load all configurations stored in the configuration file as separated yaml documents :param config_path: path to the yaml configuration file :returns: list of configurations """ return copy_deepcopy(_mutable_cached_yaml_load_all(config_path))
__all__ = [ "LegacyAwareLoader", "cached_yaml_load", "cached_yaml_load_all", ]