Skip to content

Commit 94287ab

Browse files
committed
Add more docs and command line tools
1 parent a9c1d4f commit 94287ab

28 files changed

+304
-105
lines changed

doc/api/esmvalcore.esgf.rst

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
Find and download files from ESGF
22
=================================
33

4-
This module provides the function :py:func:`esmvalcore.esgf.find_files`
5-
for searching for files on ESGF using the ESMValTool vocabulary.
6-
It returns :py:class:`esmvalcore.esgf.ESGFFile` objects, which have a convenient
7-
:py:meth:`esmvalcore.esgf.ESGFFile.download` method for downloading the file
8-
as well as a :func:`esmvalcore.esgf.download` function for downloading multiple
9-
files in parallel.
10-
11-
See :ref:`config-esgf` for instructions on configuring this module.
12-
134
esmvalcore.esgf
145
---------------
156
.. automodule:: esmvalcore.esgf
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Load data using intake-esgf
2-
===========================
1+
esmvalcore.io.intake_esgf
2+
=========================
33

44
.. automodule:: esmvalcore.io.intake_esgf
55
:no-inherited-members:

doc/api/esmvalcore.io.protocol.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Protocols for accessing data
2-
============================
1+
esmvalcore.io.protocol
2+
======================
33

44
.. automodule:: esmvalcore.io.protocol
55
:no-inherited-members:

esmvalcore/_main.py

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,97 @@ class Config:
159159
files.
160160
"""
161161

162+
def __init__(self) -> None:
163+
from rich.console import Console
164+
165+
self.console = Console()
166+
167+
def show(
168+
self,
169+
filter: tuple[str] | None = ("extra_facets",), # noqa: A002
170+
) -> None:
171+
"""Show the current configuration.
172+
173+
Parameters
174+
----------
175+
filter:
176+
Filter this list of keys. By default, the `extra_facets`
177+
key is filtered out, as it can be very large.
178+
179+
"""
180+
import yaml
181+
from nested_lookup import nested_delete
182+
from rich.syntax import Syntax
183+
184+
from esmvalcore.config import CFG
185+
186+
cfg = dict(CFG)
187+
if filter:
188+
for key in filter:
189+
cfg = nested_delete(cfg, key)
190+
exclude_msg = (
191+
", excluding the keys " + ", ".join(f"'{f}'" for f in filter)
192+
if filter
193+
else ""
194+
)
195+
self.console.print(f"# Current configuration{exclude_msg}:")
196+
self.console.print(
197+
Syntax(
198+
yaml.safe_dump(cfg),
199+
"yaml",
200+
background_color="default",
201+
),
202+
)
203+
204+
def list(self) -> None:
205+
"""List all available example configuration files."""
206+
import importlib.resources
207+
208+
import esmvalcore.config
209+
210+
config_dir = (
211+
importlib.resources.files(esmvalcore.config) / "configurations"
212+
)
213+
self.console.print("Available configuration files:")
214+
available_files = sorted(
215+
f.name
216+
for f in config_dir.iterdir()
217+
if f.suffix == ".yml" # type: ignore[attr-defined]
218+
)
219+
self.console.print("\n".join(f"- {f}" for f in available_files))
220+
221+
def copy(
222+
self,
223+
source_file: str,
224+
target_file: Path | None = None,
225+
overwrite: bool = False,
226+
) -> None:
227+
"""Copy one of the available example configuration files to the configuration directory."""
228+
import importlib.resources
229+
230+
import esmvalcore.config
231+
232+
target_dir = esmvalcore.config._config_object._get_user_config_dir() # noqa: SLF001
233+
target_file = target_dir / (
234+
source_file if target_file is None else target_file
235+
)
236+
config_dir = (
237+
importlib.resources.files(esmvalcore.config) / "configurations"
238+
)
239+
available_files = sorted(
240+
f.name
241+
for f in config_dir.iterdir()
242+
if f.suffix == ".yml" # type: ignore[attr-defined]
243+
)
244+
if source_file not in available_files:
245+
msg = (
246+
f"Configuration file {source_file} not found, choose from "
247+
f"{', '.join(available_files)}"
248+
)
249+
raise FileNotFoundError(msg)
250+
with importlib.resources.as_file(config_dir / source_file) as file:
251+
self._copy_config_file(file, target_file, overwrite=overwrite)
252+
162253
@staticmethod
163254
def _copy_config_file(
164255
in_file: Path,
@@ -184,7 +275,7 @@ def _copy_config_file(
184275
logger.info("Creating folder %s", target_folder)
185276
target_folder.mkdir(parents=True, exist_ok=True)
186277

187-
logger.info("Copying file %s to path %s.", in_file, out_file)
278+
logger.info("Copying file %s to path %s", in_file, out_file)
188279
shutil.copy2(in_file, out_file)
189280
logger.info("Copy finished.")
190281

esmvalcore/cmor/_fixes/icon/_base_fixes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ def _get_grid_from_rootpath(self, grid_name: str) -> CubeList | None:
324324
"""Try to get grid from the ICON rootpath."""
325325
glob_patterns: list[Path] = []
326326
for data_source in _get_data_sources(self.session, "ICON"): # type: ignore[arg-type]
327-
if isinstance(data_source, esmvalcore.local.DataSource):
327+
if isinstance(data_source, esmvalcore.local.LocalDataSource):
328328
glob_patterns.extend(
329329
data_source.get_glob_patterns(**self.extra_facets),
330330
)

esmvalcore/cmor/check.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import iris.exceptions
1515
import iris.util
1616
import numpy as np
17+
import yaml
1718

1819
from esmvalcore.cmor._utils import (
1920
_get_alternative_generic_lev_coord,
@@ -50,6 +51,12 @@ class CheckLevels(IntEnum):
5051
"""Do not fail for any discrepancy with CMOR standards."""
5152

5253

54+
yaml.representer.SafeRepresenter.add_representer(
55+
CheckLevels,
56+
lambda dumper, data: dumper.represent_str(data.name.lower()),
57+
)
58+
59+
5360
class CMORCheckError(Exception):
5461
"""Exception raised when a cube does not pass the CMORCheck."""
5562

esmvalcore/config/_config_object.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ def _get_user_config_dir() -> Path:
5151
f"ESMVALTOOL_CONFIG_DIR environment variable: "
5252
f"{user_config_dir} is not an existing directory"
5353
)
54-
raise NotADirectoryError(
55-
msg,
56-
)
54+
raise NotADirectoryError(msg)
5755
return user_config_dir
5856
return Path.home() / ".config" / "esmvaltool"
5957

esmvalcore/config/_config_validators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ def validate_projects(value: Any) -> Any:
347347
"""Validate projects mapping."""
348348
mapping = validate_dict(value)
349349
options_for_project: dict[str, Callable[[Any], Any]] = {
350-
"data": validate_dict,
350+
"data": validate_dict, # TODO: try to create data sources here
351351
"extra_facets": validate_dict,
352352
}
353353
for project, project_config in mapping.items():

esmvalcore/config/configurations/access-data.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ projects:
22
ACCESS:
33
data:
44
access-sub-dataset:
5-
type: "esmvalcore.local.DataSource"
5+
type: "esmvalcore.local.LocalDataSource"
66
rootpath: ~/climate_data
77
dirname_template: "{dataset}/{sub_dataset}/{exp}/{modeling_realm}/netCDF"
88
filename_template: "{sub_dataset}.{freq_attribute}-*.nc"
99
access-ocean:
10-
type: "esmvalcore.local.DataSource"
10+
type: "esmvalcore.local.LocalDataSource"
1111
rootpath: ~/climate_data
1212
dirname_template: "{dataset}/{sub_dataset}/{exp}/{modeling_realm}/netCDF"
1313
filename_template: "ocean_{freq_attribute}.nc-*"

esmvalcore/config/configurations/badc-data.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,49 @@ projects:
22
CMIP6:
33
data:
44
badc:
5-
type: "esmvalcore.local.DataSource"
5+
type: "esmvalcore.local.LocalDataSource"
66
rootpath: /badc/cmip6/data
77
dirname_template: "{project}/{activity}/{institute}/{dataset}/{exp}/{ensemble}/{mip}/{short_name}/{grid}/{version}"
88
filename_template: "{short_name}_{mip}_{dataset}_{exp}_{ensemble}_{grid}*.nc"
99
CMIP5:
1010
data:
1111
badc:
12-
type: "esmvalcore.local.DataSource"
12+
type: "esmvalcore.local.LocalDataSource"
1313
rootpath: /badc/cmip5/data
1414
dirname_template: "{project.lower}/{product}/{institute}/{dataset}/{exp}/{frequency}/{modeling_realm}/{mip}/{ensemble}/{version}"
1515
filename_template: "{short_name}_{mip}_{dataset}_{exp}_{ensemble}*.nc"
1616
CMIP3:
1717
data:
1818
badc:
19-
type: "esmvalcore.local.DataSource"
19+
type: "esmvalcore.local.LocalDataSource"
2020
rootpath: /badc/cmip3_drs/data
2121
dirname_template: "{project.lower}/output/{institute}/{dataset}/{exp}/{frequency}/{modeling_realm}/{short_name}/{ensemble}/{version}"
2222
filename_template: "{short_name}_*.nc"
2323
CORDEX:
2424
data:
2525
badc:
26-
type: "esmvalcore.local.DataSource"
26+
type: "esmvalcore.local.LocalDataSource"
2727
rootpath: /badc/cordex/data
2828
dirname_template: "{project}/output/{domain}/{institute}/{driver}/{exp}/{ensemble}/{institute}-{dataset}/{rcm_version}/{mip}/{short_name}/{version}"
2929
filename_template: "{short_name}_{domain}_{driver}_{exp}_{ensemble}_{institute}-{dataset}_{rcm_version}_{mip}*.nc"
3030
obs4MIPs:
3131
data:
3232
badc:
33-
type: "esmvalcore.local.DataSource"
33+
type: "esmvalcore.local.LocalDataSource"
3434
rootpath: /gws/nopw/j04/esmeval/obsdata-v2
3535
dirname_template: "Tier{tier}/{dataset}"
3636
filename_template: "{short_name}_*.nc"
3737
OBS6:
3838
data:
3939
badc:
40-
type: "esmvalcore.local.DataSource"
40+
type: "esmvalcore.local.LocalDataSource"
4141
rootpath: /gws/nopw/j04/esmeval/obsdata-v2
4242
dirname_template: "Tier{tier}/{dataset}"
4343
filename_template: "{project}_{dataset}_{type}_{version}_{mip}_{short_name}[_.]*nc"
4444
OBS:
4545
data:
4646
badc:
47-
type: "esmvalcore.local.DataSource"
47+
type: "esmvalcore.local.LocalDataSource"
4848
rootpath: /gws/nopw/j04/esmeval/obsdata-v2
4949
dirname_template: "Tier{tier}/{dataset}"
5050
filename_template: "{project}_{dataset}_{type}_{version}_{mip}_{short_name}[_.]*nc"

0 commit comments

Comments
 (0)