Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ authors and references it defines.
[intake-esgf configuration](https://intake-esgf.readthedocs.io/en/latest/configure.html),
so the facets in the recipe are sent to these indices, and in the other
data sources that are configured in ESMValCore, such as local directories.
The facets of the other data sources that can be completed are those in
the templates of their paths.
The facets of the other data sources that can be completed are those that
the data source can search for, for example the facets in the templates of
the paths of local data.
`timerange`, `start_year`, and `end_year` are only completed from ESGF once
`exp` is given.
The accuracy of the values depends on the metadata provided by ESGF.
Expand Down
33 changes: 14 additions & 19 deletions src/esmvaltool_language_server/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
the data sources that are configured for a project, except those that search
ESGF: the values on ESGF are found much faster by
:mod:`esmvaltool_language_server.esgf`.
The facets that can be searched for are the facets in the templates of the
paths of the data sources, for example of
The facets that can be searched for are the
:attr:`~esmvalcore.io.protocol.DataSource.searchable_facets` of the data
sources, for example the facets in the templates of the paths of
:class:`esmvalcore.io.local.LocalDataSource`, and the facets that select the
time range, from the time ranges of the files.
"""

from __future__ import annotations

import functools
import re
from typing import TYPE_CHECKING, cast

from esmvalcore.config import CFG
Expand All @@ -36,12 +36,6 @@
},
)

# Attributes of data sources with templates of the paths of their data.
_TEMPLATES = ("dirname_template", "filename_template")

# A facet in a template, e.g. {dataset} or {dataset.lower}.
_TAG = re.compile(r"{([^}.]+)(?:\.(?:lower|upper))?}")

# Facets that :meth:`esmvalcore.dataset.Dataset.from_files` cannot find the
# values of.
_NOT_SEARCHABLE = frozenset({"project", "short_name"})
Expand All @@ -68,7 +62,7 @@ def _session(project: str) -> Session | None:

@functools.cache
def known_facets(project: str) -> frozenset[str]:
"""Get the facets in the templates of the data sources of a project.
"""Get the facets that the data sources of a project can search for.

Parameters
----------
Expand All @@ -84,12 +78,13 @@ def known_facets(project: str) -> frozenset[str]:
session = _session(project)
if session is None:
return frozenset()
return frozenset(
tag
for source in load_data_sources(session, project)
for name in _TEMPLATES
if isinstance(template := getattr(source, name, None), str)
for tag in _TAG.findall(template)
return frozenset().union(
*(
# Data sources without searchable facets are deprecated in
# ESMValCore v2.16.0.
getattr(source, "searchable_facets", frozenset())
for source in load_data_sources(session, project)
),
)


Expand All @@ -106,7 +101,7 @@ def is_searchable(project: str, facet: str) -> bool:
Returns
-------
:
Whether the facet is in the templates of the data sources or selects
Whether a data source can search for the facet or the facet selects
the time range of the data.
"""
if facet in timerange.FACETS:
Expand Down Expand Up @@ -147,8 +142,8 @@ def _dataset(
},
)
dataset.session = session
# Use any value for the facets in the templates that are not given and
# that ESMValCore does not add.
# Use any value for the searchable facets that are not given and that
# ESMValCore does not add.
augmented = dataset.copy()
augmented.augment_facets()
for name in known_facets(project) - set(augmented.facets):
Expand Down
9 changes: 9 additions & 0 deletions tests/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ def test_facet_values_not_searchable() -> None:
assert files.facet_values("OBS6", {"short_name": "tas"}, "exp") == []


@pytest.mark.usefixtures("local_data")
def test_known_facets_without_searchable_facets(
monkeypatch: pytest.MonkeyPatch,
) -> None:
# Data sources without searchable facets are deprecated in ESMValCore.
monkeypatch.setattr(files, "load_data_sources", lambda *_: [object()])
assert files.known_facets("OBS6") == set()


def test_time_ranges_are_split_at_missing_years() -> None:
found = SimpleNamespace(
files=[
Expand Down
Loading