diff --git a/azure_functions_worker/bindings/__init__.py b/azure_functions_worker/bindings/__init__.py index 5e81d4e89..3d326b5dd 100644 --- a/azure_functions_worker/bindings/__init__.py +++ b/azure_functions_worker/bindings/__init__.py @@ -6,7 +6,7 @@ from .meta import check_input_type_annotation from .meta import check_output_type_annotation from .meta import has_implicit_output -from .meta import is_trigger_binding +from .meta import is_trigger_binding, load_binding_registry from .meta import from_incoming_proto, to_outgoing_proto, \ to_outgoing_param_binding from .out import Out @@ -15,6 +15,7 @@ __all__ = ( 'Out', 'Context', 'is_trigger_binding', + 'load_binding_registry', 'check_input_type_annotation', 'check_output_type_annotation', 'has_implicit_output', 'from_incoming_proto', 'to_outgoing_proto', 'TraceContext', 'RetryContext', diff --git a/azure_functions_worker/bindings/meta.py b/azure_functions_worker/bindings/meta.py index 52867a000..3f52f8d0f 100644 --- a/azure_functions_worker/bindings/meta.py +++ b/azure_functions_worker/bindings/meta.py @@ -12,21 +12,23 @@ PB_TYPE = 'rpc_data' PB_TYPE_DATA = 'data' PB_TYPE_RPC_SHARED_MEMORY = 'rpc_shared_memory' +BINDING_REGISTRY = None -def get_binding_registry(): +def load_binding_registry() -> None: func = sys.modules.get('azure.functions') # If fails to acquire customer's BYO azure-functions, load the builtin if func is None: import azure.functions as func - return func.get_binding_registry() + global BINDING_REGISTRY + BINDING_REGISTRY = func.get_binding_registry() def get_binding(bind_name: str) -> object: binding = None - registry = get_binding_registry() + registry = BINDING_REGISTRY if registry is not None: binding = registry.get(bind_name) if binding is None: diff --git a/azure_functions_worker/dispatcher.py b/azure_functions_worker/dispatcher.py index b57aa432e..d05d18392 100644 --- a/azure_functions_worker/dispatcher.py +++ b/azure_functions_worker/dispatcher.py @@ -292,6 +292,10 @@ async def _handle__worker_init_request(self, request): and is_envvar_true(PYTHON_LOAD_FUNCTIONS_INIT): import azure.functions # NoQA + # loading bindings registry and saving results to a static + # dictionary which will be later used in the invocation request + bindings.load_binding_registry() + return protos.StreamingMessage( request_id=self.request_id, worker_init_response=protos.WorkerInitResponse( @@ -567,6 +571,10 @@ async def _handle__function_environment_reload_request(self, request): func_env_reload_request.function_app_directory ) + # calling load_binding_registry again since the + # reload_customer_libraries call clears the registry + bindings.load_binding_registry() + # Change function app directory if getattr(func_env_reload_request, 'function_app_directory', None): diff --git a/tests/unittests/test_mock_blob_shared_memory_functions.py b/tests/unittests/test_mock_blob_shared_memory_functions.py index 0fdd1fafd..f3cee34ac 100644 --- a/tests/unittests/test_mock_blob_shared_memory_functions.py +++ b/tests/unittests/test_mock_blob_shared_memory_functions.py @@ -54,6 +54,7 @@ async def test_binary_blob_write_function(self): func_name = 'put_blob_as_bytes_return_http_response' async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) content_size = consts.MIN_BYTES_FOR_SHARED_MEM_TRANSFER + 10 @@ -133,6 +134,7 @@ async def test_str_blob_read_function(self): func_name = 'get_blob_as_str_return_http_response' async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) # Write binary content into shared memory @@ -199,6 +201,7 @@ async def test_str_blob_write_function(self): func_name = 'put_blob_as_str_return_http_response' async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) content_size = consts.MIN_BYTES_FOR_SHARED_MEM_TRANSFER + 10 @@ -279,6 +282,7 @@ async def test_close_shared_memory_maps(self): func_name = 'put_blob_as_bytes_return_http_response' async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) content_size = consts.MIN_BYTES_FOR_SHARED_MEM_TRANSFER + 10 @@ -334,6 +338,7 @@ async def test_shared_memory_not_used_with_small_output(self): func_name = 'put_blob_as_bytes_return_http_response' async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) content_size = consts.MIN_BYTES_FOR_SHARED_MEM_TRANSFER - 10 @@ -372,6 +377,7 @@ async def test_multiple_input_output_blobs(self): func_name = 'put_get_multiple_blobs_as_bytes_return_http_response' async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) # Input 1 @@ -514,6 +520,7 @@ async def _test_binary_blob_read_function(self, func_name): """ async with testutils.start_mockhost(script_root=self.blob_funcs_dir) \ as host: + await host.init_worker("4.17.1") await host.load_function(func_name) # Write binary content into shared memory diff --git a/tests/unittests/test_mock_durable_functions.py b/tests/unittests/test_mock_durable_functions.py index d362d805e..daeef65a0 100644 --- a/tests/unittests/test_mock_durable_functions.py +++ b/tests/unittests/test_mock_durable_functions.py @@ -11,6 +11,7 @@ async def test_mock_activity_trigger(self): async with testutils.start_mockhost( script_root=self.durable_functions_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('activity_trigger') self.assertEqual(r.response.function_id, func_id) @@ -40,6 +41,7 @@ async def test_mock_activity_trigger_no_anno(self): async with testutils.start_mockhost( script_root=self.durable_functions_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('activity_trigger_no_anno') self.assertEqual(r.response.function_id, func_id) @@ -69,6 +71,7 @@ async def test_mock_activity_trigger_dict(self): async with testutils.start_mockhost( script_root=self.durable_functions_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('activity_trigger_dict') self.assertEqual(r.response.function_id, func_id) @@ -98,6 +101,7 @@ async def test_mock_activity_trigger_int_to_float(self): async with testutils.start_mockhost( script_root=self.durable_functions_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function( 'activity_trigger_int_to_float') @@ -128,6 +132,7 @@ async def test_mock_orchestration_trigger(self): async with testutils.start_mockhost( script_root=self.durable_functions_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('orchestration_trigger') self.assertEqual(r.response.function_id, func_id) diff --git a/tests/unittests/test_mock_eventhub_functions.py b/tests/unittests/test_mock_eventhub_functions.py index 3c4e22ba3..8fa544e84 100644 --- a/tests/unittests/test_mock_eventhub_functions.py +++ b/tests/unittests/test_mock_eventhub_functions.py @@ -13,6 +13,7 @@ async def test_mock_eventhub_trigger_iot(self): async with testutils.start_mockhost( script_root=self.mock_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('eventhub_trigger_iot') self.assertEqual(r.response.function_id, func_id) @@ -56,6 +57,7 @@ async def test_mock_eventhub_cardinality_one(self): async with testutils.start_mockhost( script_root=self.mock_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('eventhub_cardinality_one') self.assertEqual(r.response.function_id, func_id) self.assertEqual(r.response.result.status, @@ -90,6 +92,7 @@ async def test_mock_eventhub_cardinality_one_bad_annotation(self): async with testutils.start_mockhost( script_root=self.mock_funcs_dir) as host: + await host.init_worker("4.17.1") # This suppose to fail since the event should not be int func_id, r = await host.load_function( 'eventhub_cardinality_one_bad_anno' @@ -102,6 +105,8 @@ async def test_mock_eventhub_cardinality_many(self): async with testutils.start_mockhost( script_root=self.mock_funcs_dir) as host: + await host.init_worker("4.17.1") + func_id, r = await host.load_function('eventhub_cardinality_many') self.assertEqual(r.response.function_id, func_id) self.assertEqual(r.response.result.status, @@ -139,6 +144,8 @@ async def test_mock_eventhub_cardinality_many_bad_annotation(self): script_root=self.mock_funcs_dir) as host: # This suppose to fail since the event should not be List[str] + await host.init_worker("4.17.1") + func_id, r = await host.load_function( 'eventhub_cardinality_many_bad_anno' ) diff --git a/tests/unittests/test_mock_generic_functions.py b/tests/unittests/test_mock_generic_functions.py index 6a72a238f..32004850f 100644 --- a/tests/unittests/test_mock_generic_functions.py +++ b/tests/unittests/test_mock_generic_functions.py @@ -11,6 +11,7 @@ async def test_mock_generic_as_str(self): async with testutils.start_mockhost( script_root=self.generic_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('foobar_as_str') self.assertEqual(r.response.function_id, func_id) @@ -38,6 +39,7 @@ async def test_mock_generic_as_bytes(self): async with testutils.start_mockhost( script_root=self.generic_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('foobar_as_bytes') self.assertEqual(r.response.function_id, func_id) @@ -65,6 +67,7 @@ async def test_mock_generic_as_str_no_anno(self): async with testutils.start_mockhost( script_root=self.generic_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('foobar_as_str_no_anno') self.assertEqual(r.response.function_id, func_id) @@ -92,6 +95,7 @@ async def test_mock_generic_as_bytes_no_anno(self): async with testutils.start_mockhost( script_root=self.generic_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('foobar_as_bytes_no_anno') self.assertEqual(r.response.function_id, func_id) @@ -119,6 +123,7 @@ async def test_mock_generic_should_not_support_implicit_output(self): async with testutils.start_mockhost( script_root=self.generic_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('foobar_implicit_output') self.assertEqual(r.response.function_id, func_id) @@ -144,6 +149,7 @@ async def test_mock_generic_should_support_without_datatype(self): async with testutils.start_mockhost( script_root=self.generic_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('foobar_with_no_datatype') self.assertEqual(r.response.function_id, func_id) diff --git a/tests/unittests/test_mock_http_functions.py b/tests/unittests/test_mock_http_functions.py index 01bf2e765..f7538065d 100644 --- a/tests/unittests/test_mock_http_functions.py +++ b/tests/unittests/test_mock_http_functions.py @@ -8,6 +8,8 @@ class TestMockHost(testutils.AsyncTestCase): async def test_call_sync_function_check_logs(self): async with testutils.start_mockhost() as host: + + await host.init_worker("4.17.1") await host.load_function('sync_logging') invoke_id, r = await host.invoke_function( @@ -36,6 +38,8 @@ async def test_call_sync_function_check_logs(self): async def test_call_async_function_check_logs(self): async with testutils.start_mockhost() as host: + + await host.init_worker("4.17.1") await host.load_function('async_logging') invoke_id, r = await host.invoke_function( @@ -77,6 +81,7 @@ async def test_handles_unsupported_messages_gracefully(self): protos.StreamingMessage( worker_heartbeat=protos.WorkerHeartbeat())) + await host.init_worker("4.17.1") _, r = await host.load_function('return_out') self.assertEqual(r.response.result.status, protos.StatusResult.Success) diff --git a/tests/unittests/test_mock_log_filtering_functions.py b/tests/unittests/test_mock_log_filtering_functions.py index ada84e63c..81e676c22 100644 --- a/tests/unittests/test_mock_log_filtering_functions.py +++ b/tests/unittests/test_mock_log_filtering_functions.py @@ -18,6 +18,7 @@ async def test_root_logger_should_be_customer_log(self): 'azure_functions_worker.dispatcher.is_system_log_category' ) as islc_mock: async with testutils.start_mockhost(script_root=self.dir) as host: + await host.init_worker("4.17.1") await host.load_function('debug_logging') await self._invoke_function(host, 'debug_logging') @@ -33,6 +34,7 @@ async def test_customer_logging_should_not_be_system_log(self): 'azure_functions_worker.dispatcher.is_system_log_category' ) as islc_mock: async with testutils.start_mockhost(script_root=self.dir) as host: + await host.init_worker("4.17.1") await host.load_function('debug_user_logging') await self._invoke_function(host, 'debug_user_logging') @@ -48,6 +50,7 @@ async def test_sdk_logger_should_be_system_log(self): 'azure_functions_worker.dispatcher.is_system_log_category' ) as islc_mock: async with testutils.start_mockhost(script_root=self.dir) as host: + await host.init_worker("4.17.1") await host.load_function('sdk_logging') await self._invoke_function(host, 'sdk_logging') @@ -65,6 +68,7 @@ async def test_sdk_submodule_logger_should_be_system_log(self): 'azure_functions_worker.dispatcher.is_system_log_category' ) as islc_mock: async with testutils.start_mockhost(script_root=self.dir) as host: + await host.init_worker("4.17.1") await host.load_function('sdk_submodule_logging') await self._invoke_function(host, 'sdk_submodule_logging') diff --git a/tests/unittests/test_mock_timer_functions.py b/tests/unittests/test_mock_timer_functions.py index c3203df76..7bdda8ee1 100644 --- a/tests/unittests/test_mock_timer_functions.py +++ b/tests/unittests/test_mock_timer_functions.py @@ -13,6 +13,7 @@ async def test_mock_timer__return_pastdue(self): async with testutils.start_mockhost( script_root=self.timer_funcs_dir) as host: + await host.init_worker("4.17.1") func_id, r = await host.load_function('return_pastdue') self.assertEqual(r.response.function_id, func_id) @@ -44,7 +45,7 @@ async def call_and_check(due: bool): async def test_mock_timer__user_event_loop(self): async with testutils.start_mockhost( script_root=self.timer_funcs_dir) as host: - + await host.init_worker("4.17.1") func_id, r = await host.load_function('user_event_loop_timer') self.assertEqual(r.response.function_id, func_id)