Skip to content

Commit

Permalink
Make list_chunkmanagers more resilient to broken entrypoints (#8736)
Browse files Browse the repository at this point in the history
* Make list_chunkmanagers more resilient to broken entrypoints

As I'm a developing my custom chunk manager, I'm often checking out
between my development branch and production branch breaking the
entrypoint.

This made xarray impossible to import unless I re-ran `pip install -e . -vv`
which is somewhat tiring.

* Type hint untyped test function to appease mypy

* Try to return something to help mypy

---------

Co-authored-by: Tom Nicholas <tom@cworthy.org>
Co-authored-by: Illviljan <14371165+Illviljan@users.noreply.github.com>
  • Loading branch information
3 people authored Mar 13, 2024
1 parent 11f89ec commit a3f7774
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 5 deletions.
4 changes: 2 additions & 2 deletions xarray/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,10 +1106,10 @@ def find_stack_level(test_mode=False) -> int:
return n


def emit_user_level_warning(message, category=None):
def emit_user_level_warning(message, category=None) -> None:
"""Emit a warning at the user level by inspecting the stack trace."""
stacklevel = find_stack_level()
warnings.warn(message, category=category, stacklevel=stacklevel)
return warnings.warn(message, category=category, stacklevel=stacklevel)


def consolidate_dask_from_array_kwargs(
Expand Down
13 changes: 10 additions & 3 deletions xarray/namedarray/parallelcompat.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import numpy as np

from xarray.core.utils import emit_user_level_warning
from xarray.namedarray.pycompat import is_chunked_array

if TYPE_CHECKING:
Expand Down Expand Up @@ -73,9 +74,15 @@ def load_chunkmanagers(
) -> dict[str, ChunkManagerEntrypoint[Any]]:
"""Load entrypoints and instantiate chunkmanagers only once."""

loaded_entrypoints = {
entrypoint.name: entrypoint.load() for entrypoint in entrypoints
}
loaded_entrypoints = {}
for entrypoint in entrypoints:
try:
loaded_entrypoints[entrypoint.name] = entrypoint.load()
except ModuleNotFoundError as e:
emit_user_level_warning(
f"Failed to load chunk manager entrypoint {entrypoint.name} due to {e}. Skipping.",
)
pass

available_chunkmanagers = {
name: chunkmanager()
Expand Down
12 changes: 12 additions & 0 deletions xarray/tests/test_parallelcompat.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from importlib.metadata import EntryPoint
from typing import Any

import numpy as np
Expand All @@ -13,6 +14,7 @@
get_chunked_array_type,
guess_chunkmanager,
list_chunkmanagers,
load_chunkmanagers,
)
from xarray.tests import has_dask, requires_dask

Expand Down Expand Up @@ -218,3 +220,13 @@ def test_raise_on_mixed_array_types(self, register_dummy_chunkmanager) -> None:

with pytest.raises(TypeError, match="received multiple types"):
get_chunked_array_type(*[dask_arr, dummy_arr])


def test_bogus_entrypoint() -> None:
# Create a bogus entry-point as if the user broke their setup.cfg
# or is actively developing their new chunk manager
entry_point = EntryPoint(
"bogus", "xarray.bogus.doesnotwork", "xarray.chunkmanagers"
)
with pytest.warns(UserWarning, match="Failed to load chunk manager"):
assert len(load_chunkmanagers([entry_point])) == 0

0 comments on commit a3f7774

Please sign in to comment.