Skip to content

Commit 7ec5ad3

Browse files
committed
Allow to pass an error_callback for the GracefulResourceRenderer.
This allows to run some code in an error case, e.g. to add a user-visible status message.
1 parent 78f31f7 commit 7ec5ad3

File tree

3 files changed

+70
-6
lines changed

3 files changed

+70
-6
lines changed

CHANGES.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Changelog
44
1.3 (unreleased)
55
----------------
66

7+
- Allow to pass an error_callback for the GracefulResourceRenderer.
8+
This allows to run some code in an error case, e.g. to add a user-visible
9+
status message.
10+
[thet]
11+
712
- Also handle resource resolver errors gracefully in the GracefulResourceRenderer.
813
[thet]
914

webresource/_api.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ def render(self):
738738
class GracefulResourceRenderer(ResourceRenderer):
739739
"""Resource renderer, which does not fail but logs an exception."""
740740

741-
def render(self):
741+
def render(self, error_callback=None):
742742
lines = []
743743
resources = []
744744

@@ -751,6 +751,8 @@ def render(self):
751751
) as e:
752752
error_message = str(e)
753753
logger.exception(error_message)
754+
if error_callback:
755+
error_callback(error_message)
754756

755757
for resource in resources:
756758
error_message = None
@@ -768,4 +770,6 @@ def render(self):
768770
error_message
769771
))
770772
logger.exception(error_message)
773+
if error_callback:
774+
error_callback(error_message)
771775
return u'\n'.join(lines)

webresource/tests.py

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,23 @@
77
ResourceConfig,
88
ResourceMixin
99
)
10+
import logging
1011
import os
1112
import shutil
1213
import tempfile
1314
import unittest
1415
import webresource as wr
1516

16-
1717
try:
1818
FileNotFoundError
1919
except NameError: # pragma: nocover
2020
FileNotFoundError = EnvironmentError
2121

2222

23+
# Get log level to restore it later
24+
original_log_level = logging.getLogger().getEffectiveLevel()
25+
26+
2327
def temp_directory(fn):
2428
def wrapper(*a, **kw):
2529
tempdir = tempfile.mkdtemp()
@@ -812,10 +816,6 @@ def test_GracefulResourceRenderer(self):
812816
))
813817

814818
def test_GreacefulResourceRenderer_resolver_errors(self):
815-
# Get log level to restore it later
816-
import logging
817-
original_log_level = logging.getLogger().getEffectiveLevel()
818-
819819
# Create a resource with a circular dependency
820820
resource = Resource(name='res1', resource='res1.ext', depends='res1')
821821

@@ -840,6 +840,61 @@ def test_GreacefulResourceRenderer_resolver_errors(self):
840840
# interactible.
841841
self.assertEqual(rendered, "")
842842

843+
def test_GreacefulResourceRenderer_callback_resolver(self):
844+
# Callback which should be called on error
845+
error_message = []
846+
847+
def callback(message):
848+
error_message.append(message)
849+
850+
# Create a resource with a circular dependency
851+
resource = Resource(name='res1', resource='res1.ext', depends='res1')
852+
853+
resolver = wr.ResourceResolver([resource])
854+
renderer = wr.GracefulResourceRenderer(resolver)
855+
856+
# Supress error traceback in logs
857+
logging.disable(logging.CRITICAL)
858+
renderer.render(error_callback=callback)
859+
# Restore logging level
860+
logging.disable(original_log_level)
861+
862+
self.assertEqual(len(error_message), 1)
863+
self.assertEqual(
864+
error_message[-1],
865+
"Resources define circular dependencies: "
866+
"""[<Resource name="res1", depends="['res1']">]"""
867+
)
868+
869+
def test_GreacefulResourceRenderer_callback_render(self):
870+
# Callback which should be called on error
871+
error_message = []
872+
873+
def callback(message):
874+
error_message.append(message)
875+
876+
# Create a resource with a circular dependency
877+
resource = wr.ScriptResource(
878+
name='res1',
879+
resource='res1.ext',
880+
unique=True
881+
)
882+
883+
resolver = wr.ResourceResolver([resource])
884+
renderer = wr.GracefulResourceRenderer(resolver)
885+
886+
# Supress error traceback in logs
887+
logging.disable(logging.CRITICAL)
888+
renderer.render(error_callback=callback)
889+
# Restore logging level
890+
logging.disable(original_log_level)
891+
892+
self.assertEqual(len(error_message), 1)
893+
self.assertEqual(
894+
error_message[-1],
895+
"""No directory set on resource <ScriptResource name="res1">"""
896+
)
897+
843898

844899
if __name__ == '__main__':
845900
unittest.main()

0 commit comments

Comments
 (0)