Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the check_satpy function to find missing dependencies #488

Merged
merged 4 commits into from
Nov 20, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ If applicable, add screenshots to help explain your problem.
**Environment Info:**
- OS: [e.g. OSX, Windows, Linux]
- SatPy Version: [e.g. 0.9.0]
- PyResample Version:
- PyResample Version:
- Readers and writers dependencies (when relevant): [run `from satpy.config import check_satpy; check_satpy()`]

**Additional context**
Add any other context about the problem here.
63 changes: 55 additions & 8 deletions satpy/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
import glob
import logging
import os
from collections import Mapping
from collections import Mapping, OrderedDict

from six.moves import configparser
import yaml

LOG = logging.getLogger(__name__)

Expand All @@ -52,8 +53,7 @@ def get_environ_ancpath(default='.'):


def runtime_import(object_path):
"""Import at runtime
"""
"""Import at runtime."""
obj_module, obj_element = object_path.rsplit(".", 1)
loader = __import__(obj_module, globals(), locals(), [str(obj_element)])
return getattr(loader, obj_element)
Expand All @@ -69,17 +69,18 @@ def config_search_paths(filename, *search_dirs, **kwargs):
# FUTURE: Remove CONFIG_PATH because it should be included as a search_dir
paths += [os.path.join(CONFIG_PATH, filename),
os.path.join(PACKAGE_CONFIG_PATH, filename)]
paths = [os.path.abspath(path) for path in paths]

if kwargs.get("check_exists", True):
paths = [x for x in paths if os.path.isfile(x)]

paths = list(OrderedDict.fromkeys(paths))
djhoese marked this conversation as resolved.
Show resolved Hide resolved
# flip the order of the list so builtins are loaded first
return paths[::-1]


def get_config(filename, *search_dirs, **kwargs):
"""Blends the different configs, from package defaults to .
"""
"""Blends the different configs, from package defaults to ."""
config = kwargs.get("config_reader_class", configparser.ConfigParser)()

paths = config_search_paths(filename, *search_dirs)
Expand All @@ -106,8 +107,7 @@ def glob_config(pattern, *search_dirs):


def get_config_path(filename, *search_dirs):
"""Get the appropriate path for a filename, in that order: filename, ., PPP_CONFIG_DIR, package's etc dir.
"""
"""Get the appropriate path for a filename, in that order: filename, ., PPP_CONFIG_DIR, package's etc dir."""
paths = config_search_paths(filename, *search_dirs)

for path in paths[::-1]:
Expand All @@ -116,7 +116,7 @@ def get_config_path(filename, *search_dirs):


def recursive_dict_update(d, u):
"""Recursive dictionary update using
"""Recursive dictionary update.

Copied from:

Expand All @@ -130,3 +130,50 @@ def recursive_dict_update(d, u):
else:
d[k] = u[k]
return d


def check_yaml_configs(configs, key, hdr_len):
"""Get a diagnostic for the yaml *configs*.

*key* is the section to look for to get a name for the config at hand.
*hdr_len* is the number of lines that can be safely read from the config to
get a name.
"""
diagnostic = {}
for i in configs:
for fname in i:
with open(fname) as stream:
try:
res = yaml.load(stream)
try:
diagnostic[res[key]['name']] = 'ok'
except Exception:
continue
except yaml.YAMLError as err:
stream.seek(0)
lines = ''.join(stream.readline() for line in range(hdr_len))
res = yaml.load(lines)
if err.context == 'while constructing a Python object':
problem = err.problem
else:
problem = 'error'
try:
diagnostic[res[key]['name']] = problem
except Exception:
continue
return diagnostic


def check_satpy():
"""Check the satpy readers and writers for correct installation."""
from satpy.readers import configs_for_reader
from satpy.writers import configs_for_writer
print('Readers')
print('=======')
for reader, res in sorted(check_yaml_configs(configs_for_reader(), 'reader', 5).items()):
print(reader + ': ' + res)
print()
print('Writers')
print('=======')
for writer, res in sorted(check_yaml_configs(configs_for_writer(), 'writer', 3).items()):
print(writer + ': ' + res)
14 changes: 9 additions & 5 deletions satpy/tests/test_writers.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def test_enhance_empty_config(self):
self.assertIsNotNone(e.enhancement_tree)
get_enhanced_image(ds, enhancer=e)
self.assertSetEqual(set(e.sensor_enhancement_configs),
{self.ENH_FN3})
{os.path.abspath(self.ENH_FN3)})

def test_enhance_with_sensor_no_entry(self):
"""Test enhancing an image that has no configuration sections."""
Expand All @@ -225,7 +225,8 @@ def test_enhance_with_sensor_no_entry(self):
self.assertIsNotNone(e.enhancement_tree)
get_enhanced_image(ds, enhancer=e)
self.assertSetEqual(set(e.sensor_enhancement_configs),
{self.ENH_FN2, self.ENH_ENH_FN2})
{os.path.abspath(self.ENH_FN2),
os.path.abspath(self.ENH_ENH_FN2)})

def test_enhance_with_sensor_entry(self):
"""Test enhancing an image with a configuration section."""
Expand All @@ -240,7 +241,8 @@ def test_enhance_with_sensor_entry(self):
img = get_enhanced_image(ds, enhancer=e)
self.assertSetEqual(
set(e.sensor_enhancement_configs),
{self.ENH_FN, self.ENH_ENH_FN})
{os.path.abspath(self.ENH_FN),
os.path.abspath(self.ENH_ENH_FN)})
np.testing.assert_almost_equal(img.data.isel(bands=0).max().values,
1.)

Expand All @@ -251,7 +253,8 @@ def test_enhance_with_sensor_entry(self):
self.assertIsNotNone(e.enhancement_tree)
img = get_enhanced_image(ds, enhancer=e)
self.assertSetEqual(set(e.sensor_enhancement_configs),
{self.ENH_FN, self.ENH_ENH_FN})
{os.path.abspath(self.ENH_FN),
os.path.abspath(self.ENH_ENH_FN)})
np.testing.assert_almost_equal(img.data.isel(bands=0).max().values, 1.)

def test_enhance_with_sensor_entry2(self):
Expand All @@ -266,7 +269,8 @@ def test_enhance_with_sensor_entry2(self):
self.assertIsNotNone(e.enhancement_tree)
img = get_enhanced_image(ds, enhancer=e)
self.assertSetEqual(set(e.sensor_enhancement_configs),
{self.ENH_FN, self.ENH_ENH_FN})
{os.path.abspath(self.ENH_FN),
os.path.abspath(self.ENH_ENH_FN)})
djhoese marked this conversation as resolved.
Show resolved Hide resolved
np.testing.assert_almost_equal(img.data.isel(bands=0).max().values, 0.5)


Expand Down