diff --git a/eng/templates/official/jobs/ci-lc-tests.yml b/eng/templates/official/jobs/ci-lc-tests.yml index eed1db324..578231392 100644 --- a/eng/templates/official/jobs/ci-lc-tests.yml +++ b/eng/templates/official/jobs/ci-lc-tests.yml @@ -12,14 +12,16 @@ jobs: strategy: matrix: - Python39: - PYTHON_VERSION: '3.9' Python310: PYTHON_VERSION: '3.10' Python311: PYTHON_VERSION: '3.11' Python312: PYTHON_VERSION: '3.12' + Python313: + PYTHON_VERSION: '3.13' + Python314: + PYTHON_VERSION: '3.14' steps: - task: UsePythonVersion@0 inputs: diff --git a/runtimes/v1/azure_functions_runtime_v1/handle_event.py b/runtimes/v1/azure_functions_runtime_v1/handle_event.py index 1b2836348..4e877e3f8 100644 --- a/runtimes/v1/azure_functions_runtime_v1/handle_event.py +++ b/runtimes/v1/azure_functions_runtime_v1/handle_event.py @@ -276,7 +276,7 @@ async def function_environment_reload_request(request): os.environ[var] = env_vars[var] if is_envvar_true(PYTHON_ENABLE_DEBUG_LOGGING): - root_logger = logging.getLogger("azure.functions") + root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) # calling load_binding_registry again since the diff --git a/runtimes/v2/azure_functions_runtime/handle_event.py b/runtimes/v2/azure_functions_runtime/handle_event.py index 082763191..3d6b8acfe 100644 --- a/runtimes/v2/azure_functions_runtime/handle_event.py +++ b/runtimes/v2/azure_functions_runtime/handle_event.py @@ -326,7 +326,7 @@ async def function_environment_reload_request(request): # TODO: Apply PYTHON_THREADPOOL_THREAD_COUNT if is_envvar_true(PYTHON_ENABLE_DEBUG_LOGGING): - root_logger = logging.getLogger("azure.functions") + root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) # calling load_binding_registry again since the diff --git a/workers/tests/consumption_tests/test_linux_consumption.py b/workers/tests/consumption_tests/test_linux_consumption.py index 109a6806c..d8bc9d2a5 100644 --- a/workers/tests/consumption_tests/test_linux_consumption.py +++ b/workers/tests/consumption_tests/test_linux_consumption.py @@ -213,16 +213,7 @@ def test_reload_variables_after_oom_error(self): sleep(2) logs = ctrl.get_container_logs() - self.assertRegex( - logs, - r"Applying prioritize_customer_dependencies: " - r"worker_dependencies_path: \/azure-functions-host\/" - r"workers\/python\/.*?\/LINUX\/X64," - r" customer_dependencies_path: \/home\/site\/wwwroot\/" - r"\.python_packages\/lib\/site-packages, working_directory:" - r" \/home\/site\/wwwroot, Linux Consumption: True," - r" Placeholder: False") - + assert "Finished prioritize_customer_dependencies" in logs self.assertNotIn("Failure Exception: ModuleNotFoundError", logs) diff --git a/workers/tests/utils/testutils_lc.py b/workers/tests/utils/testutils_lc.py index 94979adb0..bae6b9278 100644 --- a/workers/tests/utils/testutils_lc.py +++ b/workers/tests/utils/testutils_lc.py @@ -26,8 +26,12 @@ # Linux Consumption Testing Constants _DOCKER_PATH = "DOCKER_PATH" _DOCKER_DEFAULT_PATH = "docker" -_MESH_IMAGE_URL = "https://mcr.microsoft.com/v2/azure-functions/mesh/tags/list" -_MESH_IMAGE_REPO = "mcr.microsoft.com/azure-functions/mesh" +_OS_TYPE = "bookworm" if sys.version_info.minor < 14 else "noble" +_MESH_IMAGE_URL = ( + f"https://mcr.microsoft.com/v2/azure-functions/{_OS_TYPE}/" + "flexconsumption/tags/list" +) +_MESH_IMAGE_REPO = f"mcr.microsoft.com/azure-functions/{_OS_TYPE}/flexconsumption" _FUNC_GITHUB_ZIP = "https://github.com/Azure/azure-functions-python-library" \ "/archive/refs/heads/dev.zip" _FUNC_FILE_NAME = "azure-functions-python-library-dev" @@ -219,7 +223,37 @@ def spawn_container(self, container according to the image name. Return the port of container. """ # Construct environment variables and start the docker container - worker_path = os.path.join(PROJECT_ROOT, 'azure_functions_worker') + worker_name = 'azure_functions_worker' \ + if sys.version_info.minor < 13 else 'proxy_worker' + + worker_path = os.path.join(PROJECT_ROOT, worker_name) + container_worker_path = ( + f"/azure-functions-host/workers/python/{self._py_version}/" + f"LINUX/X64/{worker_name}" + ) + + # For Python 3.13+, also mount the runtime libraries + runtime_v2_path = None + runtime_v1_path = None + container_runtime_v2_path = None + container_runtime_v1_path = None + + if sys.version_info.minor >= 13: + repo_root = os.path.dirname(PROJECT_ROOT) + runtime_v2_path = os.path.join( + repo_root, 'runtimes', 'v2', 'azure_functions_runtime' + ) + runtime_v1_path = os.path.join( + repo_root, 'runtimes', 'v1', 'azure_functions_runtime_v1' + ) + container_runtime_v2_path = ( + f"/azure-functions-host/workers/python/{self._py_version}/" + "LINUX/X64/azure_functions_runtime" + ) + container_runtime_v1_path = ( + f"/azure-functions-host/workers/python/{self._py_version}/" + "LINUX/X64/azure_functions_runtime_v1" + ) # TODO: Mount library in docker container # self._download_azure_functions() @@ -227,11 +261,6 @@ def spawn_container(self, # Download python extension base package ext_folder = self._download_extensions() - container_worker_path = ( - f"/azure-functions-host/workers/python/{self._py_version}/" - "LINUX/X64/azure_functions_worker" - ) - base_ext_container_path = ( f"/azure-functions-host/workers/python/{self._py_version}/" "LINUX/X64/azurefunctions/extensions/base" @@ -255,6 +284,16 @@ def spawn_container(self, run_cmd.extend(["-e", f"WEBSITE_SITE_NAME={self._uuid}"]) run_cmd.extend(["-e", "WEBSITE_SKU=Dynamic"]) run_cmd.extend(["-v", f'{worker_path}:{container_worker_path}']) + + # Mount runtime libraries for Python 3.13+ + if runtime_v2_path and runtime_v1_path: + run_cmd.extend([ + "-v", f'{runtime_v2_path}:{container_runtime_v2_path}' + ]) + run_cmd.extend([ + "-v", f'{runtime_v1_path}:{container_runtime_v1_path}' + ]) + run_cmd.extend(["-v", f'{base_ext_local_path}:{base_ext_container_path}'])