Repository: ioos/compliance-checker

Issue:
Exception during reasoning output
Running the CF checker on [this file](http://thredds.aodn.org.au/thredds/catalog/IMOS/eMII/checker_test/ANFOG/delayed/catalog.html?dataset=IMOS/eMII/checker_test/ANFOG/delayed/IMOS_ANFOG_BCEOPSTUV_20140915T003743Z_SL209_FV01_timeseries_END-20141009T212310Z.nc), I get the following exception during the printing of the reasoning messages:

```
Name                             Priority:     Score:Reasoning
--------------------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/mhidas/bin/cchecker.py", line 36, in <module>
    sys.exit(main())
  File "/home/mhidas/bin/cchecker.py", line 27, in main
    args.format)
  File "/home/mhidas/code/compliance-checker/compliance_checker/runner.py", line 56, in run_checker
    groups = cls.stdout_output(cs, score_groups, verbose, limit)
  File "/home/mhidas/code/compliance-checker/compliance_checker/runner.py", line 91, in stdout_output
    cs.non_verbose_output_generation(score_list, groups, limit, points, out_of)
  File "/home/mhidas/code/compliance-checker/compliance_checker/suite.py", line 280, in non_verbose_output_generation
    self.reasoning_routine(groups, 0)
  File "/home/mhidas/code/compliance-checker/compliance_checker/suite.py", line 369, in reasoning_routine
    print wrapper.fill('%-39s:%1s:%6s/%2s : %s' %(str(indent*'    '+res.name)[0:39], res.weight, str(res.value[0]), str(res.value[1]), str(", ".join(res.msgs))))
TypeError: sequence item 0: expected string, tuple found
```



Discussion:

Resolving patch:
diff --git a/compliance_checker/cf/cf.py b/compliance_checker/cf/cf.py
--- a/compliance_checker/cf/cf.py
+++ b/compliance_checker/cf/cf.py
@@ -378,8 +378,7 @@ def check_fill_value_outside_valid_range(self, ds):
         """
         2.5.1 The _FillValue should be outside the range specified by valid_range (if used) for a variable.
         """
-        fails = []
-        checked = 0
+        ret = []
 
         for k, v in ds.dataset.variables.iteritems():
             if hasattr(v, '_FillValue'):
@@ -387,20 +386,22 @@ def check_fill_value_outside_valid_range(self, ds):
 
                 if 'valid_range' in attrs:
                     rmin, rmax = v.valid_range
+                    spec_by = 'valid_range'
                 elif 'valid_min' in attrs and 'valid_max' in attrs:
                     rmin = v.valid_min
                     rmax = v.valid_max
+                    spec_by = 'valid_min/valid_max'
                 else:
                     continue
 
-                checked += 1
+                valid     = not (v._FillValue >= rmin and v._FillValue <= rmax)
+                reasoning = []
+                if not valid:
+                    reasoning = ["%s must not be in valid range (%s to %s) as specified by %s" % (v._FillValue, rmin, rmax, spec_by)]
 
-                if v._FillValue >= rmin and v._FillValue <= rmax:
-                    fails.append((k, "%s is between %s and %s" % (v._FillValue, rmin, rmax)))
-        if checked >= 1:
-            return Result(BaseCheck.HIGH, (checked - len(fails), checked), msgs=fails)
-        else:
-            return []
+                ret.append(Result(BaseCheck.HIGH, valid, ('_FillValue', k, 'outside_valid_range'), msgs=reasoning))
+
+        return ret
 
     def check_conventions_are_cf_16(self, ds):
         """


Test patch:
diff --git a/compliance_checker/tests/test_cf.py b/compliance_checker/tests/test_cf.py
--- a/compliance_checker/tests/test_cf.py
+++ b/compliance_checker/tests/test_cf.py
@@ -171,8 +171,9 @@ def test_check_fill_value_outside_valid_range(self):
         """
 
         dataset = self.get_pair(static_files['bad_data_type'])
-        result = self.cf.check_fill_value_outside_valid_range(dataset)
-        assert result.value == (1, 2)
+        results = self.cf.check_fill_value_outside_valid_range(dataset)
+        assert sum((result.value for result in results)) == 1
+        assert len(results) == 2
 
     def test_check_conventions_are_cf_16(self):
         """