From f942cee1937220b662b1b62f0db2457006360464 Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Wed, 1 Oct 2025 10:57:41 -0700 Subject: [PATCH 1/4] Test to ensure that all imports in datadog-lambda-python still valid. --- tests/internal/test_serverless.py | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/internal/test_serverless.py b/tests/internal/test_serverless.py index 0e3454c2719..d72a9800f54 100644 --- a/tests/internal/test_serverless.py +++ b/tests/internal/test_serverless.py @@ -103,3 +103,56 @@ def find_spec(self, fullname, *args): assert stdout.decode() == "" assert stderr.decode() == "" assert status == 0 + + +@pytest.mark.parametrize( + "from_,import_", + [ + ("ddtrace", "__version__"), + ("ddtrace", "patch"), + ("ddtrace", "patch_all"), + ("ddtrace._trace._span_pointer", "_SpanPointerDescription"), + ("ddtrace._trace._span_pointer", "_SpanPointerDirection"), + ("ddtrace._trace.utils_botocore.span_pointers.dynamodb", "_aws_dynamodb_item_span_pointer_description"), + ("ddtrace._trace.utils_botocore.span_pointers.s3", "_aws_s3_object_span_pointer_description"), + ("ddtrace.contrib.internal.trace_utils", "_get_request_header_client_ip"), + ("ddtrace.data_streams", "set_consume_checkpoint"), + ("ddtrace.debugging._exception.replay", "SpanExceptionHandler"), + ("ddtrace.debugging._uploader", "SignalUploader"), + ("ddtrace.internal", "core"), + ("ddtrace.internal._exceptions", "BlockingException"), + ("ddtrace.internal.appsec.product", "start"), + ("ddtrace.internal.telemetry", "telemetry_writer"), + ("ddtrace.internal.utils", "get_blocked"), + ("ddtrace.internal.utils", "http"), + ("ddtrace.llmobs", "LLMObs"), + ("ddtrace.opentelemetry", "TracerProvider"), + ("ddtrace.profiling", "profiler"), + ("ddtrace.propagation.http", "HTTPPropagator"), + ("ddtrace.trace", "Context, Span, tracer"), + ("ddtrace.trace", "Span"), + ("ddtrace.trace", "tracer"), + ], +) +def test_serverless_imports(from_, import_, run_python_code_in_subprocess): + # datadog-lambda-python imports a bunch of packages from ddtrace. This + # test ensures that none of those imports break. If this test fails, then + # either you will need to retain the import that was removed or you must + # update datadog-lambda-python to support the new import path. + import os + + env = os.environ.copy() + env.update( + { + "AWS_LAMBDA_FUNCTION_NAME": "foobar", + "DD_INSTRUMENTATION_TELEMETRY_ENABLED": "False", + "DD_API_SECURITY_ENABLED": "False", + } + ) + + code = f"from {from_} import {import_}" + + stderr, stdout, status, _ = run_python_code_in_subprocess(code, env=env) + assert stdout.decode() == "" + assert stderr.decode() == "" + assert status == 0 From c2dca6989e96d9f5db8025a745dd183f6426cb62 Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Fri, 3 Oct 2025 14:28:51 -0700 Subject: [PATCH 2/4] Skip failing test only for python >=3.14 --- tests/internal/test_serverless.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/internal/test_serverless.py b/tests/internal/test_serverless.py index d72a9800f54..a0c01e731c5 100644 --- a/tests/internal/test_serverless.py +++ b/tests/internal/test_serverless.py @@ -1,4 +1,5 @@ import pytest +import sys from ddtrace.internal.serverless import in_azure_function from ddtrace.internal.serverless import in_gcp_function @@ -127,7 +128,14 @@ def find_spec(self, fullname, *args): ("ddtrace.internal.utils", "http"), ("ddtrace.llmobs", "LLMObs"), ("ddtrace.opentelemetry", "TracerProvider"), - ("ddtrace.profiling", "profiler"), + pytest.param( + "ddtrace.profiling", + "profiler", + marks=pytest.mark.xfail( + reason="import throws error AttributeError: module 'asyncio.events' has no attribute 'BaseDefaultEventLoopPolicy'", + condition=sys.version_info >= (3, 14), + ), + ), ("ddtrace.propagation.http", "HTTPPropagator"), ("ddtrace.trace", "Context, Span, tracer"), ("ddtrace.trace", "Span"), From 17f33b85f657ece3a2d83a24e04ee1200422b5bf Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Fri, 3 Oct 2025 14:35:41 -0700 Subject: [PATCH 3/4] Ruff. --- tests/internal/test_serverless.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/internal/test_serverless.py b/tests/internal/test_serverless.py index a0c01e731c5..1bc811de27d 100644 --- a/tests/internal/test_serverless.py +++ b/tests/internal/test_serverless.py @@ -1,6 +1,7 @@ -import pytest import sys +import pytest + from ddtrace.internal.serverless import in_azure_function from ddtrace.internal.serverless import in_gcp_function from tests.utils import override_env @@ -132,7 +133,7 @@ def find_spec(self, fullname, *args): "ddtrace.profiling", "profiler", marks=pytest.mark.xfail( - reason="import throws error AttributeError: module 'asyncio.events' has no attribute 'BaseDefaultEventLoopPolicy'", + reason="throws AttributeError: module 'asyncio.events' has no attribute 'BaseDefaultEventLoopPolicy'", condition=sys.version_info >= (3, 14), ), ), From 73c096120980a98e7419c6fe3b7ad592987a1bd5 Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Mon, 6 Oct 2025 10:21:52 -0400 Subject: [PATCH 4/4] Set xfail strict. --- tests/internal/test_serverless.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/internal/test_serverless.py b/tests/internal/test_serverless.py index 1bc811de27d..47858d2e6d6 100644 --- a/tests/internal/test_serverless.py +++ b/tests/internal/test_serverless.py @@ -132,9 +132,11 @@ def find_spec(self, fullname, *args): pytest.param( "ddtrace.profiling", "profiler", + # when 3.14 is officially supported, this xfail can be removed. marks=pytest.mark.xfail( reason="throws AttributeError: module 'asyncio.events' has no attribute 'BaseDefaultEventLoopPolicy'", condition=sys.version_info >= (3, 14), + strict=True, ), ), ("ddtrace.propagation.http", "HTTPPropagator"),