Skip to content

Commit

Permalink
Merge pull request #11919 from dbaston/cpl-quiet-warnings
Browse files Browse the repository at this point in the history
Add CPLQuietWarningsErrorHandler
  • Loading branch information
rouault authored Mar 5, 2025
2 parents 6d3dd57 + 1c404c6 commit cf9dc1a
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 1 deletion.
34 changes: 34 additions & 0 deletions autotest/gcore/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import gdaltest
import pytest
from test_py_scripts import run_py_script_as_external_script

from osgeo import gdal, osr

Expand Down Expand Up @@ -1126,6 +1127,39 @@ def test_misc_gdal_driver_has_open_option(driver_name, open_option, expected):
assert driver.HasOpenOption(open_option) == expected


###############################################################################
# Test gdal.quiet_errors() and gdal.quiet_warnings()


@pytest.mark.parametrize("context", ("quiet_errors", "quiet_warnings"))
def test_misc_quiet_errors(tmp_path, context):

script = f"""
from osgeo import gdal
with gdal.{context}():
gdal.Error(gdal.CE_Debug, gdal.CPLE_AppDefined, "Debug")
gdal.Error(gdal.CE_Warning, gdal.CPLE_AppDefined, "Warning")
gdal.Error(gdal.CE_Failure, gdal.CPLE_AppDefined, "Failure")
"""

with open(tmp_path / "script.py", "w") as f:
f.write(script)

out, err = run_py_script_as_external_script(
tmp_path, "script", "", return_stderr=True
)
if context == "quiet_errors":
assert "Debug" in err
assert "Warning" not in err
assert "Failure" not in err

if context == "quiet_warnings":
assert "Debug" in err
assert "Warning" not in err
assert "Failure" in err


###############################################################################


Expand Down
14 changes: 14 additions & 0 deletions port/cpl_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,20 @@ void CPL_STDCALL CPLQuietErrorHandler(CPLErr eErrClass, CPLErrorNum nError,
CPLDefaultErrorHandler(eErrClass, nError, pszErrorMsg);
}

/************************************************************************/
/* CPLQuietWarningsErrorHandler() */
/************************************************************************/

/** Error handler that ignores CE_Warning messages. */
void CPL_STDCALL CPLQuietWarningsErrorHandler(CPLErr eErrClass,
CPLErrorNum nError,
const char *pszErrorMsg)

{
if (eErrClass != CE_Warning)
CPLDefaultErrorHandler(eErrClass, nError, pszErrorMsg);
}

/************************************************************************/
/* CPLLoggingErrorHandler() */
/************************************************************************/
Expand Down
2 changes: 2 additions & 0 deletions port/cpl_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ void CPL_DLL CPL_STDCALL CPLDefaultErrorHandler(CPLErr, CPLErrorNum,
const char *);
void CPL_DLL CPL_STDCALL CPLQuietErrorHandler(CPLErr, CPLErrorNum,
const char *);
void CPL_DLL CPL_STDCALL CPLQuietWarningsErrorHandler(CPLErr, CPLErrorNum,
const char *);
void CPL_DLL CPLTurnFailureIntoWarning(int bOn);

CPLErrorHandler CPL_DLL CPLGetErrorHandler(void **ppUserData);
Expand Down
2 changes: 2 additions & 0 deletions swig/include/cpl.i
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, CPLErrorNum err_no, const c
CPLErrorHandler pfnHandler = NULL;
if( pszCallbackName == NULL || EQUAL(pszCallbackName,"CPLQuietErrorHandler") )
pfnHandler = CPLQuietErrorHandler;
else if( EQUAL(pszCallbackName,"CPLQuietWarningsErrorHandler") )
pfnHandler = CPLQuietWarningsErrorHandler;
else if( EQUAL(pszCallbackName,"CPLDefaultErrorHandler") )
pfnHandler = CPLDefaultErrorHandler;
else if( EQUAL(pszCallbackName,"CPLLoggingErrorHandler") )
Expand Down
24 changes: 23 additions & 1 deletion swig/include/python/gdal_python.i
Original file line number Diff line number Diff line change
Expand Up @@ -4957,7 +4957,7 @@ def config_option(key, value, thread_local=True):

@contextlib.contextmanager
def quiet_errors():
"""Temporarily install an error handler that silents all warnings and errors.
"""Temporarily install an error handler that silences all warnings and errors.
Returns
-------
Expand All @@ -4975,6 +4975,28 @@ def quiet_errors():
finally:
PopErrorHandler()

@contextlib.contextmanager
def quiet_warnings():
"""Temporarily install an error handler that silences all warnings.
.. versionadded: 3.11
Returns
-------
A context manager
Example
-------
>>> with gdal.ExceptionMgr(useExceptions=False), gdal.quiet_warnings():
... gdal.Error(gdal.CE_Warning, gdal.CPLE_AppDefined, "you will never see me")
"""
PushErrorHandler("CPLQuietWarningsErrorHandler")
try:
yield
finally:
PopErrorHandler()

%}


Expand Down
2 changes: 2 additions & 0 deletions swig/include/python/typemaps_python.i
Original file line number Diff line number Diff line change
Expand Up @@ -1820,6 +1820,8 @@ static PyObject *XMLTreeToPyList( CPLXMLNode *psTree )
{
if( pszCallbackName == NULL || EQUAL(pszCallbackName,"CPLQuietErrorHandler") )
$1 = CPLQuietErrorHandler;
else if( EQUAL(pszCallbackName,"CPLQuietWarningsErrorHandler") )
$1 = CPLQuietWarningsErrorHandler;
else if( EQUAL(pszCallbackName,"CPLDefaultErrorHandler") )
$1 = CPLDefaultErrorHandler;
else if( EQUAL(pszCallbackName,"CPLLoggingErrorHandler") )
Expand Down

0 comments on commit cf9dc1a

Please sign in to comment.