Repository: cogeotiff/rio-cogeo

Issue:
cog_validate should return warnings and errors
In order to use `cog_validate` in other APIs I think it will be good to make it return the info instead of printing them 👇 

https://github.com/cogeotiff/rio-cogeo/blob/6fda1dc1904ea9317c776e709677af2cb2a698f6/rio_cogeo/cogeo.py#L438-L452

Discussion:

Patch:
diff --git a/rio_cogeo/cogeo.py b/rio_cogeo/cogeo.py
index 8f2a551..c6f158e 100644
--- a/rio_cogeo/cogeo.py
+++ b/rio_cogeo/cogeo.py
@@ -6,7 +6,7 @@ import sys
 import tempfile
 import warnings
 from contextlib import ExitStack, contextmanager
-from typing import Any, Dict
+from typing import Any, Dict, List, Tuple
 
 import click
 import rasterio
@@ -288,7 +288,9 @@ def cog_translate(
                 copy(tmp_dst, dst_path, copy_src_overviews=True, **dst_kwargs)
 
 
-def cog_validate(src_path: str, strict: bool = False, quiet: bool = False):
+def cog_validate(
+    src_path: str, strict: bool = False, quiet: bool = False
+) -> Tuple[bool, List[str], List[str]]:
     """
     Validate Cloud Optimized Geotiff.
 
@@ -300,6 +302,8 @@ def cog_validate(src_path: str, strict: bool = False, quiet: bool = False):
         Treat warnings as errors
     quiet: bool
         Remove standard outputs
+    return_errors: bool
+        Return errors and warnings
 
     This script is the rasterio equivalent of
     https://svn.osgeo.org/gdal/trunk/gdal/swig/python/samples/validate_cloud_optimized_geotiff.py
@@ -446,7 +450,6 @@ def cog_validate(src_path: str, strict: bool = False, quiet: bool = False):
         for e in errors:
             click.echo("- " + e, err=True)
 
-    if errors or (warnings and strict):
-        return False
+    is_valid = False if errors or (warnings and strict) else True
 
-    return True
+    return is_valid, errors, warnings
diff --git a/rio_cogeo/scripts/cli.py b/rio_cogeo/scripts/cli.py
index c40979b..f8708df 100644
--- a/rio_cogeo/scripts/cli.py
+++ b/rio_cogeo/scripts/cli.py
@@ -253,7 +253,8 @@ def create(
 @click.option("--strict", default=False, is_flag=True, help="Treat warnings as errors.")
 def validate(input, strict):
     """Validate Cloud Optimized Geotiff."""
-    if cog_validate(input, strict=strict):
+    is_valid, _, _ = cog_validate(input, strict=strict)
+    if is_valid:
         click.echo("{} is a valid cloud optimized GeoTIFF".format(input))
     else:
         click.echo("{} is NOT a valid cloud optimized GeoTIFF".format(input))


Test patch:
diff --git a/tests/test_validate.py b/tests/test_validate.py
index 791fb04..c670564 100644
--- a/tests/test_validate.py
+++ b/tests/test_validate.py
@@ -34,28 +34,40 @@ jpeg_profile.update({"blockxsize": 256, "blockysize": 256})
 def test_cog_validate_valid(monkeypatch):
     """Should work as expected (validate cogeo file)."""
     # not tiled but 512x512
-    assert cog_validate(raster_rgb)
+    assert cog_validate(raster_rgb)[0]
 
     # not tiled, no overview
-    assert not cog_validate(raster_big, quiet=True)
+    assert not cog_validate(raster_big, quiet=True)[0]
 
     # external overview
-    assert not cog_validate(raster_external)
+    assert not cog_validate(raster_external)[0]
 
     # non-sorted overview
-    assert not cog_validate(raster_ovrsorted)
+    assert not cog_validate(raster_ovrsorted)[0]
 
     # invalid decimation
-    assert not cog_validate(raster_decim)
+    assert not cog_validate(raster_decim)[0]
 
     # no overview
-    assert cog_validate(raster_no_ovr)
-    assert not cog_validate(raster_no_ovr, strict=True)
+    assert cog_validate(raster_no_ovr)[0]
+    assert not cog_validate(raster_no_ovr, strict=True)[0]
 
     with pytest.raises(Exception):
         cog_validate(raster_jpeg)
 
 
+def test_cog_validate_return():
+    valid, err, warn = cog_validate(raster_rgb)
+    assert valid
+    assert not err
+    assert not warn
+
+    valid, err, warn = cog_validate(raster_no_ovr)
+    assert valid
+    assert len(warn) == 1
+    assert not err
+
+
 def test_cog_validate_validCreatioValid(monkeypatch):
     """Should work as expected (validate cogeo file)."""
     runner = CliRunner()