Source code for esmvalcore.experimental.utils

"""ESMValCore utilities."""

import os
import re
from pathlib import Path
from typing import Optional, Pattern, Tuple, Union

from esmvalcore.config._diagnostics import DIAGNOSTICS

from .recipe import Recipe


[docs] class RecipeList(list): """Container for recipes."""
[docs] def find(self, query: Pattern[str]): """Search for recipes matching the search query or pattern. Searches in the description, authors and project information fields. All matches are returned. Parameters ---------- query : str, Pattern String to search for, e.g. ``find_recipes('righi')`` will return all matching that author. Can be a `regex` pattern. Returns ------- RecipeList List of recipes matching the search query. """ query = re.compile(query, flags=re.IGNORECASE) matches = RecipeList() for recipe in self: match = re.search(query, str(recipe)) if match: matches.append(recipe) return matches
[docs] def get_all_recipes(subdir: Optional[str] = None) -> list: """Return a list of all available recipes. Parameters ---------- subdir : str Sub-directory of the ``DIAGNOSTICS.path`` to look for recipes, e.g. ``get_all_recipes(subdir='examples')``. Returns ------- RecipeList List of available recipes """ if subdir is None: subdir = '**' rootdir = DIAGNOSTICS.recipes files = rootdir.glob(f'{subdir}/*.yml') return RecipeList(Recipe(file) for file in files)
[docs] def get_recipe(name: Union[os.PathLike, str]) -> Recipe: """Get a recipe by its name. The function looks first in the local directory, and second in the repository defined by the diagnostic path. The recipe name can be specified with or without extension. The first match will be returned. Parameters ---------- name : str, pathlike Name of the recipe file, i.e. ``examples/recipe_python.yml`` Returns ------- Recipe Instance of :obj:`Recipe` which can be used to inspect and run the recipe. Raises ------ FileNotFoundError If the name cannot be resolved to a recipe file. """ filenames: Tuple[Union[str, os.PathLike], ...] locations = Path(), DIAGNOSTICS.recipes if isinstance(name, str): filenames = (name, name + '.yml') else: filenames = (name, ) for location in locations: for filename in filenames: try_path = Path(location, filename).expanduser() if try_path.exists(): return Recipe(try_path) raise FileNotFoundError(f'Could not find `{name}` in {locations}.')