diff --git a/doc/source/_static/main.js b/doc/source/_static/main.js
index 6fcd3ce79a..188a335e71 100644
--- a/doc/source/_static/main.js
+++ b/doc/source/_static/main.js
@@ -1,5 +1,6 @@
$(document).ready( function () {
$('table.datatable').DataTable( {
- "paging": false
+ "paging": false,
+ "dom": 'lfitp'
} );
} );
diff --git a/doc/source/reader_table.py b/doc/source/reader_table.py
index 3982728f47..1c6760a390 100644
--- a/doc/source/reader_table.py
+++ b/doc/source/reader_table.py
@@ -18,6 +18,8 @@
# along with satpy. If not, see .
"""Module for autogenerating reader table from config files."""
+from yaml import BaseLoader
+
from satpy.readers import available_readers
@@ -72,7 +74,7 @@ def generate_reader_table():
table = [rst_table_header("Satpy Readers", header=["Description", "Reader name", "Status", "fsspec support"],
widths=[45, 25, 30, 30])]
- reader_configs = available_readers(as_dict=True)
+ reader_configs = available_readers(as_dict=True, yaml_loader=BaseLoader)
for rc in reader_configs:
table.append(rst_table_row([rc.get("long_name", "").rstrip("\n"), rc.get("name", ""),
rc.get("status", ""), rc.get("supports_fsspec", "false")]))
diff --git a/satpy/composites/config_loader.py b/satpy/composites/config_loader.py
index 58f6b2a2bb..4550ca58b9 100644
--- a/satpy/composites/config_loader.py
+++ b/satpy/composites/config_loader.py
@@ -25,11 +25,7 @@
from typing import Callable, Iterable
import yaml
-
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
+from yaml import UnsafeLoader
import satpy
from satpy import DataID, DataQuery
diff --git a/satpy/plugin_base.py b/satpy/plugin_base.py
index 65660ba1f0..ee19341796 100644
--- a/satpy/plugin_base.py
+++ b/satpy/plugin_base.py
@@ -20,11 +20,7 @@
import logging
import yaml
-
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
+from yaml import UnsafeLoader
from satpy._config import config_search_paths
from satpy.utils import recursive_dict_update
diff --git a/satpy/readers/__init__.py b/satpy/readers/__init__.py
index a789623f62..de9efd26e4 100644
--- a/satpy/readers/__init__.py
+++ b/satpy/readers/__init__.py
@@ -26,11 +26,7 @@
from functools import total_ordering
import yaml
-
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
+from yaml import UnsafeLoader
from satpy._config import config_search_paths, get_entry_points_config_dirs, glob_config
@@ -370,22 +366,24 @@ def get_valid_reader_names(reader):
return new_readers
-def available_readers(as_dict=False):
+def available_readers(as_dict=False, yaml_loader=UnsafeLoader):
"""Available readers based on current configuration.
Args:
as_dict (bool): Optionally return reader information as a dictionary.
- Default: False
+ Default: False.
+ yaml_loader (Optional[Union[yaml.BaseLoader, yaml.FullLoader, yaml.UnsafeLoader]]):
+ The yaml loader type. Default: ``yaml.UnsafeLoader``.
- Returns: List of available reader names. If `as_dict` is `True` then
- a list of dictionaries including additionally reader information
- is returned.
+ Returns:
+ Union[list[str], list[dict]]: List of available reader names. If `as_dict` is `True` then
+ a list of dictionaries including additionally reader information is returned.
"""
readers = []
for reader_configs in configs_for_reader():
try:
- reader_info = read_reader_config(reader_configs)
+ reader_info = read_reader_config(reader_configs, loader=yaml_loader)
except (KeyError, IOError, yaml.YAMLError):
LOG.debug("Could not import reader config from: %s", reader_configs)
LOG.debug("Error loading YAML", exc_info=True)
@@ -454,12 +452,12 @@ def find_files_and_readers(start_time=None, end_time=None, base_dir=None,
missing_ok (bool): If False (default), raise ValueError if no files
are found. If True, return empty dictionary if no
files are found.
- fs (FileSystem): Optional, instance of implementation of
- fsspec.spec.AbstractFileSystem (strictly speaking,
- any object of a class implementing ``.glob`` is
- enough). Defaults to searching the local filesystem.
+ fs (:class:`fsspec.spec.AbstractFileSystem`): Optional, instance of implementation of
+ :class:`fsspec.spec.AbstractFileSystem` (strictly speaking, any object of a class implementing
+ ``.glob`` is enough). Defaults to searching the local filesystem.
- Returns: Dictionary mapping reader name string to list of filenames
+ Returns:
+ dict: Dictionary mapping reader name string to list of filenames
"""
reader_files = {}
diff --git a/satpy/readers/yaml_reader.py b/satpy/readers/yaml_reader.py
index 2e3203e5a8..97eb7510bd 100644
--- a/satpy/readers/yaml_reader.py
+++ b/satpy/readers/yaml_reader.py
@@ -26,22 +26,16 @@
from collections import OrderedDict, deque
from contextlib import suppress
from fnmatch import fnmatch
+from functools import cached_property
from weakref import WeakValueDictionary
import numpy as np
import xarray as xr
import yaml
-
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
-
-from functools import cached_property
-
from pyresample.boundary import AreaDefBoundary, Boundary
from pyresample.geometry import AreaDefinition, StackedAreaDefinition, SwathDefinition
from trollsift.parser import globify, parse
+from yaml import UnsafeLoader
from satpy import DatasetDict
from satpy.aux_download import DataDownloadMixin
diff --git a/satpy/tests/test_readers.py b/satpy/tests/test_readers.py
index 6a30ba09fa..3f76e63596 100644
--- a/satpy/tests/test_readers.py
+++ b/satpy/tests/test_readers.py
@@ -17,7 +17,9 @@
# satpy. If not, see .
"""Test classes and functions in the readers/__init__.py module."""
+import builtins
import os
+import sys
import unittest
from contextlib import suppress
from unittest import mock
@@ -55,6 +57,8 @@
},
}
+real_import = builtins.__import__
+
def make_dataid(**items):
"""Make a data id."""
@@ -625,6 +629,11 @@ def test_old_reader_name_mapping(self):
class TestYAMLFiles(unittest.TestCase):
"""Test and analyze the reader configuration files."""
+ def setUp(self):
+ """Set up monkeypatch."""
+ from _pytest.monkeypatch import MonkeyPatch
+ self.monkeypatch = MonkeyPatch()
+
def test_filename_matches_reader_name(self):
"""Test that every reader filename matches the name in the YAML."""
import yaml
@@ -662,6 +671,29 @@ def test_available_readers(self):
self.assertIn('name', reader_info)
self.assertEqual(reader_infos, sorted(reader_infos, key=lambda reader_info: reader_info['name']))
+ def test_available_readers_base_loader(self):
+ """Test the 'available_readers' function for yaml loader type BaseLoader."""
+ import yaml
+
+ from satpy import available_readers
+ from satpy._config import glob_config
+
+ def patched_import_error(name, globals=None, locals=None, fromlist=(), level=0):
+ if name in ('netcdf4', ):
+ raise ImportError(f"Mocked import error {name}")
+ return real_import(name, globals=globals, locals=locals, fromlist=fromlist, level=level)
+
+ self.monkeypatch.delitem(sys.modules, 'netcdf4', raising=False)
+ self.monkeypatch.setattr(builtins, '__import__', patched_import_error)
+
+ with pytest.raises(ImportError):
+ import netcdf4 # noqa: F401
+
+ reader_names = available_readers(yaml_loader=yaml.BaseLoader)
+ self.assertIn('abi_l1b', reader_names) # needs netcdf4
+ self.assertIn('viirs_l1b', reader_names)
+ self.assertEqual(len(reader_names), len(list(glob_config('readers/*.yaml'))))
+
class TestGroupFiles(unittest.TestCase):
"""Test the 'group_files' utility function."""
diff --git a/satpy/utils.py b/satpy/utils.py
index e1489a9c19..26efc90bf5 100644
--- a/satpy/utils.py
+++ b/satpy/utils.py
@@ -31,15 +31,10 @@
import numpy as np
import xarray as xr
import yaml
-from yaml import BaseLoader
+from yaml import BaseLoader, UnsafeLoader
from satpy import CHUNK_SIZE
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
-
_is_logging_on = False
TRACE_LEVEL = 5
diff --git a/satpy/writers/__init__.py b/satpy/writers/__init__.py
index f31a6008f6..655b42571c 100644
--- a/satpy/writers/__init__.py
+++ b/satpy/writers/__init__.py
@@ -29,14 +29,9 @@
import numpy as np
import xarray as xr
import yaml
-
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
-
from trollimage.xrimage import XRImage
from trollsift import parser
+from yaml import UnsafeLoader
from satpy import CHUNK_SIZE
from satpy._config import config_search_paths, get_entry_points_config_dirs, glob_config
diff --git a/setup.py b/setup.py
index 0e700c37ae..cdddac0058 100644
--- a/setup.py
+++ b/setup.py
@@ -31,7 +31,7 @@
pass
requires = ['numpy >=1.13', 'pillow', 'pyresample >=1.24.0', 'trollsift',
- 'trollimage >1.10.1', 'pykdtree', 'pyyaml', 'xarray >=0.10.1, !=0.13.0',
+ 'trollimage >1.10.1', 'pykdtree', 'pyyaml >=5.1', 'xarray >=0.10.1, !=0.13.0',
'dask[array] >=0.17.1', 'pyproj>=2.2', 'zarr', 'donfig', 'appdirs',
'pooch', 'pyorbital']
diff --git a/utils/convert_to_ninjotiff.py b/utils/convert_to_ninjotiff.py
index 1c3eef595e..e457ee35e3 100644
--- a/utils/convert_to_ninjotiff.py
+++ b/utils/convert_to_ninjotiff.py
@@ -30,17 +30,12 @@
import os
import yaml
+from yaml import UnsafeLoader
from satpy import Scene
from satpy.pyresample import get_area_def
from satpy.utils import debug_on
-try:
- from yaml import UnsafeLoader
-except ImportError:
- from yaml import Loader as UnsafeLoader # type: ignore
-
-
debug_on()
parser = argparse.ArgumentParser(description='Turn an image into a NinjoTiff.')