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}.")