Skip to content

Commit 6e4d667

Browse files
authored
Sort backends (#4886)
* style * order the plugins and tests * style * fix post merge * fix plugin_test * capitalize global variable
1 parent 2a34bfb commit 6e4d667

File tree

2 files changed

+65
-23
lines changed

2 files changed

+65
-23
lines changed

xarray/backends/plugins.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88

99
from .common import BACKEND_ENTRYPOINTS
1010

11+
STANDARD_BACKENDS_ORDER = ["netcdf4", "h5netcdf", "scipy"]
1112

12-
def remove_duplicates(backend_entrypoints):
13+
14+
def remove_duplicates(pkg_entrypoints):
1315

1416
# sort and group entrypoints by name
15-
backend_entrypoints = sorted(backend_entrypoints, key=lambda ep: ep.name)
16-
backend_entrypoints_grouped = itertools.groupby(
17-
backend_entrypoints, key=lambda ep: ep.name
18-
)
17+
pkg_entrypoints = sorted(pkg_entrypoints, key=lambda ep: ep.name)
18+
pkg_entrypoints_grouped = itertools.groupby(pkg_entrypoints, key=lambda ep: ep.name)
1919
# check if there are multiple entrypoints for the same name
20-
unique_backend_entrypoints = []
21-
for name, matches in backend_entrypoints_grouped:
20+
unique_pkg_entrypoints = []
21+
for name, matches in pkg_entrypoints_grouped:
2222
matches = list(matches)
23-
unique_backend_entrypoints.append(matches[0])
23+
unique_pkg_entrypoints.append(matches[0])
2424
matches_len = len(matches)
2525
if matches_len > 1:
2626
selected_module_name = matches[0].module_name
@@ -30,7 +30,7 @@ def remove_duplicates(backend_entrypoints):
3030
f"\n {all_module_names}.\n It will be used: {selected_module_name}.",
3131
RuntimeWarning,
3232
)
33-
return unique_backend_entrypoints
33+
return unique_pkg_entrypoints
3434

3535

3636
def detect_parameters(open_dataset):
@@ -51,13 +51,13 @@ def detect_parameters(open_dataset):
5151
return tuple(parameters_list)
5252

5353

54-
def create_engines_dict(backend_entrypoints):
55-
engines = {}
56-
for backend_ep in backend_entrypoints:
57-
name = backend_ep.name
58-
backend = backend_ep.load()
59-
engines[name] = backend
60-
return engines
54+
def backends_dict_from_pkg(pkg_entrypoints):
55+
backend_entrypoints = {}
56+
for pkg_ep in pkg_entrypoints:
57+
name = pkg_ep.name
58+
backend = pkg_ep.load()
59+
backend_entrypoints[name] = backend
60+
return backend_entrypoints
6161

6262

6363
def set_missing_parameters(backend_entrypoints):
@@ -67,11 +67,23 @@ def set_missing_parameters(backend_entrypoints):
6767
backend.open_dataset_parameters = detect_parameters(open_dataset)
6868

6969

70-
def build_engines(entrypoints):
70+
def sort_backends(backend_entrypoints):
71+
ordered_backends_entrypoints = {}
72+
for be_name in STANDARD_BACKENDS_ORDER:
73+
if backend_entrypoints.get(be_name, None) is not None:
74+
ordered_backends_entrypoints[be_name] = backend_entrypoints.pop(be_name)
75+
ordered_backends_entrypoints.update(
76+
{name: backend_entrypoints[name] for name in sorted(backend_entrypoints)}
77+
)
78+
return ordered_backends_entrypoints
79+
80+
81+
def build_engines(pkg_entrypoints):
7182
backend_entrypoints = BACKEND_ENTRYPOINTS.copy()
72-
pkg_entrypoints = remove_duplicates(entrypoints)
73-
external_backend_entrypoints = create_engines_dict(pkg_entrypoints)
83+
pkg_entrypoints = remove_duplicates(pkg_entrypoints)
84+
external_backend_entrypoints = backends_dict_from_pkg(pkg_entrypoints)
7485
backend_entrypoints.update(external_backend_entrypoints)
86+
backend_entrypoints = sort_backends(backend_entrypoints)
7587
set_missing_parameters(backend_entrypoints)
7688
engines = {}
7789
for name, backend in backend_entrypoints.items():
@@ -81,8 +93,8 @@ def build_engines(entrypoints):
8193

8294
@functools.lru_cache(maxsize=1)
8395
def list_engines():
84-
entrypoints = pkg_resources.iter_entry_points("xarray.backends")
85-
return build_engines(entrypoints)
96+
pkg_entrypoints = pkg_resources.iter_entry_points("xarray.backends")
97+
return build_engines(pkg_entrypoints)
8698

8799

88100
def guess_engine(store_spec):

xarray/tests/test_plugins.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ def test_remove_duplicates_warnings(dummy_duplicated_entrypoints):
5858

5959

6060
@mock.patch("pkg_resources.EntryPoint.load", mock.MagicMock(return_value=None))
61-
def test_create_engines_dict():
61+
def test_backends_dict_from_pkg():
6262
specs = [
6363
"engine1 = xarray.tests.test_plugins:backend_1",
6464
"engine2 = xarray.tests.test_plugins:backend_2",
6565
]
6666
entrypoints = [pkg_resources.EntryPoint.parse(spec) for spec in specs]
67-
engines = plugins.create_engines_dict(entrypoints)
67+
engines = plugins.backends_dict_from_pkg(entrypoints)
6868
assert len(engines) == 2
6969
assert engines.keys() == set(("engine1", "engine2"))
7070

@@ -111,8 +111,38 @@ def test_build_engines():
111111
"cfgrib = xarray.tests.test_plugins:backend_1"
112112
)
113113
backend_entrypoints = plugins.build_engines([dummy_pkg_entrypoint])
114+
114115
assert isinstance(backend_entrypoints["cfgrib"], DummyBackendEntrypoint1)
115116
assert backend_entrypoints["cfgrib"].open_dataset_parameters == (
116117
"filename_or_obj",
117118
"decoder",
118119
)
120+
121+
122+
@mock.patch(
123+
"pkg_resources.EntryPoint.load",
124+
mock.MagicMock(return_value=DummyBackendEntrypoint1),
125+
)
126+
def test_build_engines_sorted():
127+
dummy_pkg_entrypoints = [
128+
pkg_resources.EntryPoint.parse(
129+
"dummy2 = xarray.tests.test_plugins:backend_1",
130+
),
131+
pkg_resources.EntryPoint.parse(
132+
"dummy1 = xarray.tests.test_plugins:backend_1",
133+
),
134+
]
135+
backend_entrypoints = plugins.build_engines(dummy_pkg_entrypoints)
136+
backend_entrypoints = list(backend_entrypoints)
137+
138+
indices = []
139+
for be in plugins.STANDARD_BACKENDS_ORDER:
140+
try:
141+
index = backend_entrypoints.index(be)
142+
backend_entrypoints.pop(index)
143+
indices.append(index)
144+
except ValueError:
145+
pass
146+
147+
assert set(indices) < {0, -1}
148+
assert list(backend_entrypoints) == sorted(backend_entrypoints)

0 commit comments

Comments
 (0)