Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cb3405b

Browse files
committedJul 31, 2024·
Raise all init errors in init instead of suppressing them until the fist
invoke
1 parent dc83706 commit cb3405b

File tree

2 files changed

+21
-66
lines changed

2 files changed

+21
-66
lines changed
 

‎awslambdaric/bootstrap.py

+13-14
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,30 @@ def _get_handler(handler):
4141
FaultException.MALFORMED_HANDLER_NAME,
4242
"Bad handler '{}': {}".format(handler, str(e)),
4343
)
44-
return make_fault_handler(fault)
44+
raise fault
4545

4646
try:
4747
if modname.split(".")[0] in sys.builtin_module_names:
4848
fault = FaultException(
4949
FaultException.BUILT_IN_MODULE_CONFLICT,
5050
"Cannot use built-in module {} as a handler module".format(modname),
5151
)
52-
return make_fault_handler(fault)
52+
raise fault
5353
m = importlib.import_module(modname.replace("/", "."))
5454
except ImportError as e:
5555
fault = FaultException(
5656
FaultException.IMPORT_MODULE_ERROR,
5757
"Unable to import module '{}': {}".format(modname, str(e)),
5858
)
59-
request_handler = make_fault_handler(fault)
60-
return request_handler
59+
raise fault
6160
except SyntaxError as e:
6261
trace = [' File "%s" Line %s\n %s' % (e.filename, e.lineno, e.text)]
6362
fault = FaultException(
6463
FaultException.USER_CODE_SYNTAX_ERROR,
6564
"Syntax error in module '{}': {}".format(modname, str(e)),
6665
trace,
6766
)
68-
request_handler = make_fault_handler(fault)
69-
return request_handler
67+
raise fault
7068

7169
try:
7270
request_handler = getattr(m, fname)
@@ -76,15 +74,8 @@ def _get_handler(handler):
7674
"Handler '{}' missing on module '{}'".format(fname, modname),
7775
None,
7876
)
79-
request_handler = make_fault_handler(fault)
80-
return request_handler
81-
82-
83-
def make_fault_handler(fault):
84-
def result(*args):
8577
raise fault
86-
87-
return result
78+
return request_handler
8879

8980

9081
def make_error(
@@ -475,15 +466,23 @@ def run(app_root, handler, lambda_runtime_api_addr):
475466
lambda_runtime_client = LambdaRuntimeClient(
476467
lambda_runtime_api_addr, use_thread_for_polling_next
477468
)
469+
error_result = None
478470

479471
try:
480472
_setup_logging(_AWS_LAMBDA_LOG_FORMAT, _AWS_LAMBDA_LOG_LEVEL, log_sink)
481473
global _GLOBAL_AWS_REQUEST_ID
482474

483475
request_handler = _get_handler(handler)
476+
except FaultException as e:
477+
error_result = make_error(
478+
e.msg,
479+
e.exception_type,
480+
e.trace,
481+
)
484482
except Exception:
485483
error_result = build_fault_result(sys.exc_info(), None)
486484

485+
if error_result is not None:
487486
log_error(error_result, log_sink)
488487
lambda_runtime_client.post_init_error(to_json(error_result))
489488

‎tests/test_bootstrap.py

+8-52
Original file line numberDiff line numberDiff line change
@@ -603,43 +603,6 @@ def raise_exception_handler(json_input, lambda_context):
603603

604604
self.assertEqual(mock_stdout.getvalue(), error_logs)
605605

606-
# The order of patches matter. Using MagicMock resets sys.stdout to the default.
607-
@patch("importlib.import_module")
608-
@patch("sys.stdout", new_callable=StringIO)
609-
def test_handle_event_request_fault_exception_logging_syntax_error(
610-
self, mock_stdout, mock_import_module
611-
):
612-
try:
613-
eval("-")
614-
except SyntaxError as e:
615-
syntax_error = e
616-
617-
mock_import_module.side_effect = syntax_error
618-
619-
response_handler = bootstrap._get_handler("a.b")
620-
621-
bootstrap.handle_event_request(
622-
self.lambda_runtime,
623-
response_handler,
624-
"invoke_id",
625-
self.event_body,
626-
"application/json",
627-
{},
628-
{},
629-
"invoked_function_arn",
630-
0,
631-
bootstrap.StandardLogSink(),
632-
)
633-
error_logs = (
634-
lambda_unhandled_exception_warning_message
635-
+ f"[ERROR] Runtime.UserCodeSyntaxError: Syntax error in module 'a': {syntax_error}\r"
636-
)
637-
error_logs += "Traceback (most recent call last):\r"
638-
error_logs += '  File "<string>" Line 1\r'
639-
error_logs += "    -\n"
640-
641-
self.assertEqual(mock_stdout.getvalue(), error_logs)
642-
643606

644607
class TestXrayFault(unittest.TestCase):
645608
def test_make_xray(self):
@@ -717,10 +680,8 @@ def __eq__(self, other):
717680

718681
def test_get_event_handler_bad_handler(self):
719682
handler_name = "bad_handler"
720-
response_handler = bootstrap._get_handler(handler_name)
721683
with self.assertRaises(FaultException) as cm:
722-
response_handler()
723-
684+
response_handler = bootstrap._get_handler(handler_name)
724685
returned_exception = cm.exception
725686
self.assertEqual(
726687
self.FaultExceptionMatcher(
@@ -732,9 +693,8 @@ def test_get_event_handler_bad_handler(self):
732693

733694
def test_get_event_handler_import_error(self):
734695
handler_name = "no_module.handler"
735-
response_handler = bootstrap._get_handler(handler_name)
736696
with self.assertRaises(FaultException) as cm:
737-
response_handler()
697+
response_handler = bootstrap._get_handler(handler_name)
738698
returned_exception = cm.exception
739699
self.assertEqual(
740700
self.FaultExceptionMatcher(
@@ -757,10 +717,9 @@ def test_get_event_handler_syntax_error(self):
757717
filename_w_ext = os.path.basename(tmp_file.name)
758718
filename, _ = os.path.splitext(filename_w_ext)
759719
handler_name = "{}.syntax_error".format(filename)
760-
response_handler = bootstrap._get_handler(handler_name)
761720

762721
with self.assertRaises(FaultException) as cm:
763-
response_handler()
722+
response_handler = bootstrap._get_handler(handler_name)
764723
returned_exception = cm.exception
765724
self.assertEqual(
766725
self.FaultExceptionMatcher(
@@ -782,9 +741,8 @@ def test_get_event_handler_missing_error(self):
782741
filename_w_ext = os.path.basename(tmp_file.name)
783742
filename, _ = os.path.splitext(filename_w_ext)
784743
handler_name = "{}.my_handler".format(filename)
785-
response_handler = bootstrap._get_handler(handler_name)
786744
with self.assertRaises(FaultException) as cm:
787-
response_handler()
745+
response_handler = bootstrap._get_handler(handler_name)
788746
returned_exception = cm.exception
789747
self.assertEqual(
790748
self.FaultExceptionMatcher(
@@ -801,9 +759,8 @@ def test_get_event_handler_slash(self):
801759
response_handler()
802760

803761
def test_get_event_handler_build_in_conflict(self):
804-
response_handler = bootstrap._get_handler("sys.hello")
805762
with self.assertRaises(FaultException) as cm:
806-
response_handler()
763+
response_handler = bootstrap._get_handler("sys.hello")
807764
returned_exception = cm.exception
808765
self.assertEqual(
809766
self.FaultExceptionMatcher(
@@ -1452,9 +1409,8 @@ def test_set_log_level_with_dictConfig(self, mock_stderr, mock_stdout):
14521409

14531410

14541411
class TestBootstrapModule(unittest.TestCase):
1455-
@patch("awslambdaric.bootstrap.handle_event_request")
14561412
@patch("awslambdaric.bootstrap.LambdaRuntimeClient")
1457-
def test_run(self, mock_runtime_client, mock_handle_event_request):
1413+
def test_run(self, mock_runtime_client):
14581414
expected_app_root = "/tmp/test/app_root"
14591415
expected_handler = "app.my_test_handler"
14601416
expected_lambda_runtime_api_addr = "test_addr"
@@ -1467,12 +1423,12 @@ def test_run(self, mock_runtime_client, mock_handle_event_request):
14671423
MagicMock(),
14681424
]
14691425

1470-
with self.assertRaises(TypeError):
1426+
with self.assertRaises(SystemExit) as cm:
14711427
bootstrap.run(
14721428
expected_app_root, expected_handler, expected_lambda_runtime_api_addr
14731429
)
14741430

1475-
mock_handle_event_request.assert_called_once()
1431+
self.assertEqual(cm.exception.code, 1)
14761432

14771433
@patch(
14781434
"awslambdaric.bootstrap.LambdaLoggerHandler",

0 commit comments

Comments
 (0)
Please sign in to comment.