From 8794b91c071603dd73e5dfb35e9fccce258928ae Mon Sep 17 00:00:00 2001 From: nvasiu Date: Tue, 5 May 2026 18:12:29 +0000 Subject: [PATCH 1/2] feat: add lambda bundled runtime useragent header - Detect whether the SDK is installed under the Lambda runtime path. If so, update the UserAgent header string. --- .../lambda_service.py | 5 ++- tests/lambda_service_test.py | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/aws_durable_execution_sdk_python/lambda_service.py b/src/aws_durable_execution_sdk_python/lambda_service.py index 51a0049..02cd6f1 100644 --- a/src/aws_durable_execution_sdk_python/lambda_service.py +++ b/src/aws_durable_execution_sdk_python/lambda_service.py @@ -3,6 +3,7 @@ import copy import datetime import logging +import os from collections.abc import MutableMapping from dataclasses import dataclass, field from enum import Enum @@ -33,6 +34,8 @@ OperationPayload: TypeAlias = str TimeoutSeconds: TypeAlias = int +_IS_RUNTIME_BUNDLED: bool = os.path.dirname(__file__).startswith("/var/lang") + logger = logging.getLogger(__name__) @@ -1061,7 +1064,7 @@ def initialize_client(cls) -> LambdaClient: config=Config( connect_timeout=5, read_timeout=50, - user_agent_extra=f"aws-durable-execution-sdk-python/{__version__}", + user_agent_extra=f"aws-durable-execution-sdk-python/{__version__}{'-bundled' if _IS_RUNTIME_BUNDLED else ''}", ), ) return cls(client=cls._cached_boto_client) diff --git a/tests/lambda_service_test.py b/tests/lambda_service_test.py index 9c9def5..98d6e9f 100644 --- a/tests/lambda_service_test.py +++ b/tests/lambda_service_test.py @@ -2047,6 +2047,45 @@ def test_lambda_client_initialize_client_no_endpoint( assert isinstance(client, LambdaClient) +@patch("aws_durable_execution_sdk_python.lambda_service._IS_RUNTIME_BUNDLED", True) +@patch.dict("os.environ", {}, clear=True) +@patch("boto3.client") +def test_lambda_client_user_agent_runtime_bundled( + mock_boto_client, reset_lambda_client_cache +): + """Test user agent includes -bundled when SDK is installed in Lambda runtime path.""" + mock_client = Mock() + mock_boto_client.return_value = mock_client + + client = LambdaClient.initialize_client() + + call_args = mock_boto_client.call_args + config = call_args[1]["config"] + assert ( + config.user_agent_extra + == f"aws-durable-execution-sdk-python/{__version__}-bundled" + ) + assert isinstance(client, LambdaClient) + + +@patch("aws_durable_execution_sdk_python.lambda_service._IS_RUNTIME_BUNDLED", False) +@patch.dict("os.environ", {}, clear=True) +@patch("boto3.client") +def test_lambda_client_user_agent_not_runtime_bundled( + mock_boto_client, reset_lambda_client_cache +): + """Test user agent does not include -bundled when SDK is customer-installed.""" + mock_client = Mock() + mock_boto_client.return_value = mock_client + + client = LambdaClient.initialize_client() + + call_args = mock_boto_client.call_args + config = call_args[1]["config"] + assert config.user_agent_extra == f"aws-durable-execution-sdk-python/{__version__}" + assert isinstance(client, LambdaClient) + + def test_lambda_client_checkpoint_with_non_none_client_token(): """Test LambdaClient.checkpoint with non-None client_token.""" mock_client = Mock() From 596166ccb1fa2826634a3a09822cebb5eb4f0be4 Mon Sep 17 00:00:00 2001 From: yaythomas Date: Wed, 6 May 2026 16:24:12 -0700 Subject: [PATCH 2/2] feat: amend isruntime check on dir --- .../lambda_service.py | 14 ++++-- tests/lambda_service_test.py | 48 +++++++++++++++---- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/aws_durable_execution_sdk_python/lambda_service.py b/src/aws_durable_execution_sdk_python/lambda_service.py index 02cd6f1..aa78e4e 100644 --- a/src/aws_durable_execution_sdk_python/lambda_service.py +++ b/src/aws_durable_execution_sdk_python/lambda_service.py @@ -3,7 +3,6 @@ import copy import datetime import logging -import os from collections.abc import MutableMapping from dataclasses import dataclass, field from enum import Enum @@ -34,11 +33,18 @@ OperationPayload: TypeAlias = str TimeoutSeconds: TypeAlias = int -_IS_RUNTIME_BUNDLED: bool = os.path.dirname(__file__).startswith("/var/lang") - logger = logging.getLogger(__name__) +def _is_in_var_dir(module_file: str = __file__) -> bool: + """Return True if this SDK is installed under /var/lang/. + + Lambda bundled Python runtimes install packages at + /var/lang/lib/pythonX.Y/site-packages/. + """ + return module_file.startswith("/var/lang/") + + # region model class OperationAction(Enum): START = "START" @@ -1064,7 +1070,7 @@ def initialize_client(cls) -> LambdaClient: config=Config( connect_timeout=5, read_timeout=50, - user_agent_extra=f"aws-durable-execution-sdk-python/{__version__}{'-bundled' if _IS_RUNTIME_BUNDLED else ''}", + user_agent_extra=f"aws-durable-execution-sdk-python/{__version__}{'-bundled' if _is_in_var_dir() else ''}", ), ) return cls(client=cls._cached_boto_client) diff --git a/tests/lambda_service_test.py b/tests/lambda_service_test.py index 98d6e9f..626be29 100644 --- a/tests/lambda_service_test.py +++ b/tests/lambda_service_test.py @@ -38,6 +38,7 @@ TimestampConverter, WaitDetails, WaitOptions, + _is_in_var_dir, ) @@ -2047,13 +2048,15 @@ def test_lambda_client_initialize_client_no_endpoint( assert isinstance(client, LambdaClient) -@patch("aws_durable_execution_sdk_python.lambda_service._IS_RUNTIME_BUNDLED", True) -@patch.dict("os.environ", {}, clear=True) +@patch( + "aws_durable_execution_sdk_python.lambda_service._is_in_var_dir", + return_value=True, +) @patch("boto3.client") def test_lambda_client_user_agent_runtime_bundled( - mock_boto_client, reset_lambda_client_cache + mock_boto_client, _mock_is_in_var_dir, reset_lambda_client_cache ): - """Test user agent includes -bundled when SDK is installed in Lambda runtime path.""" + """user_agent_extra includes -bundled when SDK is in /var/lang/.""" mock_client = Mock() mock_boto_client.return_value = mock_client @@ -2068,13 +2071,15 @@ def test_lambda_client_user_agent_runtime_bundled( assert isinstance(client, LambdaClient) -@patch("aws_durable_execution_sdk_python.lambda_service._IS_RUNTIME_BUNDLED", False) -@patch.dict("os.environ", {}, clear=True) +@patch( + "aws_durable_execution_sdk_python.lambda_service._is_in_var_dir", + return_value=False, +) @patch("boto3.client") def test_lambda_client_user_agent_not_runtime_bundled( - mock_boto_client, reset_lambda_client_cache + mock_boto_client, _mock_is_in_var_dir, reset_lambda_client_cache ): - """Test user agent does not include -bundled when SDK is customer-installed.""" + """user_agent_extra omits -bundled when SDK is not in /var/lang.""" mock_client = Mock() mock_boto_client.return_value = mock_client @@ -2086,6 +2091,33 @@ def test_lambda_client_user_agent_not_runtime_bundled( assert isinstance(client, LambdaClient) +@pytest.mark.parametrize( + "path,expected", + [ + # Lambda bundled runtime site-packages + ( + "/var/lang/lib/python3.13/site-packages/aws_durable_execution_sdk_python/lambda_service.py", + True, + ), + ( + "/var/lang/lib/python3.12/site-packages/aws_durable_execution_sdk_python/lambda_service.py", + True, + ), + # Customer deployment package + ("/var/task/aws_durable_execution_sdk_python/lambda_service.py", False), + # Lambda Layer + ("/opt/python/aws_durable_execution_sdk_python/lambda_service.py", False), + # Trailing-slash guard: /var/langsurprise must not match + ("/var/langsurprise/lib/python3.13/site-packages/x.py", False), + # Local dev + ("/Users/me/project/.venv/lib/python3.12/site-packages/x.py", False), + ("", False), + ], +) +def test_is_in_var_dir(path, expected): + assert _is_in_var_dir(path) is expected + + def test_lambda_client_checkpoint_with_non_none_client_token(): """Test LambdaClient.checkpoint with non-None client_token.""" mock_client = Mock()