diff --git a/geoviews/__init__.py b/geoviews/__init__.py index d5f8935e..e1fd5b5d 100644 --- a/geoviews/__init__.py +++ b/geoviews/__init__.py @@ -6,7 +6,6 @@ from holoviews import render, save # noqa (API import) -from .annotators import annotate # noqa (API import) from .element import ( # noqa (API import) _Element, Feature, Tiles, WMTS, LineContours, FilledContours, Text, Image, ImageStack, Points, Path, Polygons, Shape, Dataset, RGB, @@ -14,10 +13,8 @@ HexTiles, Labels, Rectangles, Segments, WindBarbs ) from .util import from_xarray # noqa (API import) -from .operation import project # noqa (API import) from ._warnings import GeoviewsDeprecationWarning, GeoviewsUserWarning # noqa: F401 from . import data # noqa (API import) -from . import operation # noqa (API import) from . import plotting # noqa (API import) from . import feature # noqa (API import) from . import tile_sources # noqa (API import) @@ -42,3 +39,30 @@ def _missing_cmd(*args,**kw): return("install pyct to enable this command (e.g. def _err(): raise ValueError(_missing_cmd()) fetch_data = copy_examples = examples = _err del partial, _examples, _copy, _fetch + + +def __getattr__(attr): + # Lazy loading heavy modules + if attr == 'annotate': + from .annotators import annotate + return annotate + elif attr == 'project': + from .operation import project + return project + elif attr == 'operation': + from . import operation + return operation + raise AttributeError(f"module {__name__} has no attribute {attr!r}") + +__all__ = [k for k in locals() if not k.startswith('_')] +__all__ += ['annotate', 'project', 'operation'] + +def __dir__(): + return __all__ + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .annotators import annotate + from .operation import project + from . import operation diff --git a/geoviews/element/geo.py b/geoviews/element/geo.py index 4968eec1..a6b4deb4 100644 --- a/geoviews/element/geo.py +++ b/geoviews/element/geo.py @@ -26,13 +26,16 @@ ) from shapely.ops import unary_union -try: - from iris.cube import Cube -except (ImportError, OSError): - # OSError because environment variable $UDUNITS2_XML_PATH - # is sometimes not set. Should be done automatically - # when installing the package. - Cube = None +def _get_iris_cube(): + try: + from iris.cube import Cube + except (ImportError, OSError): + # OSError because environment variable $UDUNITS2_XML_PATH + # is sometimes not set. Should be done automatically + # when installing the package. + Cube = None + return Cube + try: from owslib.wmts import WebMapTileService @@ -99,7 +102,7 @@ def __init__(self, data, kdims=None, vdims=None, **kwargs): crs_data = data.data else: crs_data = data - if Cube and isinstance(crs_data, Cube): + if hasattr(crs_data, 'coord_system') and _get_iris_cube() and isinstance(crs_data, _get_iris_cube()): coord_sys = crs_data.coord_system() if hasattr(coord_sys, 'as_cartopy_projection'): crs = coord_sys.as_cartopy_projection() diff --git a/geoviews/tests/conftest.py b/geoviews/tests/conftest.py index 56f8af7f..0e0bbaa9 100644 --- a/geoviews/tests/conftest.py +++ b/geoviews/tests/conftest.py @@ -1,12 +1,19 @@ -import contextlib +from contextlib import suppress +import geoviews as gv -with contextlib.suppress(ImportError): +with suppress(Exception): + gv.extension("bokeh") + +with suppress(Exception): + gv.extension("matplotlib") + +with suppress(ImportError): import matplotlib.pyplot as plt plt.switch_backend("agg") -with contextlib.suppress(Exception): +with suppress(Exception): # From Dask 2024.3.0 they now use `dask_expr` by default # https://github.com/dask/dask/issues/10995 import dask diff --git a/geoviews/tests/test_import.py b/geoviews/tests/test_import.py new file mode 100644 index 00000000..66750249 --- /dev/null +++ b/geoviews/tests/test_import.py @@ -0,0 +1,20 @@ +import sys +from subprocess import check_output +from textwrap import dedent + + +def test_no_blocklist_imports(): + check = """\ + import sys + import geoviews as gv + + blocklist = {"panel", "IPython", "datashader", "iris", "dask"} + mods = blocklist & set(sys.modules) + + if mods: + print(", ".join(mods), end="") + """ + + output = check_output([sys.executable, '-c', dedent(check)]) + + assert output == b""