Skip to content

Commit 68fad0d

Browse files
authored
test(internal): check that ddtrace does not force-load lazy modules (#4855)
## Description This change adds a test to ensure that the import of ddtrace does not cause lazy modules to be force-loaded when the ModuleWatchdog is installed on start-up. ## Checklist - [x] Followed the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines) when writing a release note. - [x] Add additional sections for `feat` and `fix` pull requests. - [x] [Library documentation](https://github.com/DataDog/dd-trace-py/tree/1.x/docs) and/or [Datadog's documentation site](https://github.com/DataDog/documentation/) is updated. Link to doc PR in description. ## Reviewer Checklist - [x] Title is accurate. - [x] Description motivates each change. - [x] No unnecessary changes were introduced in this PR. - [x] Avoid breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Tests provided or description of manual testing performed is included in the code or PR. - [x] Release note has been added and follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines), or else `changelog/no-changelog` label added. - [x] All relevant GitHub issues are correctly linked. - [x] Backports are identified and tagged with Mergifyio.
1 parent 287ef50 commit 68fad0d

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

tests/conftest.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from _pytest.runner import CallInfo
1212
from _pytest.runner import TestReport
1313
from _pytest.runner import call_and_report
14+
from _pytest.runner import pytest_runtest_protocol as default_pytest_runtest_protocol
1415
import pytest
1516
from six import PY2
1617

@@ -231,6 +232,13 @@ def _subprocess_wrapper():
231232

232233
@pytest.hookimpl(tryfirst=True)
233234
def pytest_runtest_protocol(item):
235+
if item.get_closest_marker("skip"):
236+
return default_pytest_runtest_protocol(item, None)
237+
238+
skipif = item.get_closest_marker("skipif")
239+
if skipif and skipif.args[0]:
240+
return default_pytest_runtest_protocol(item, None)
241+
234242
marker = item.get_closest_marker("subprocess")
235243
if marker:
236244
params = marker.kwargs.get("parametrize", None)

tests/internal/lazy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print("lazy loaded")

tests/internal/test_module.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,39 @@ def test_module_watchdog_dict_shallow_copy():
339339
assert original_modules == new_modules
340340

341341
ModuleWatchdog.uninstall()
342+
343+
344+
@pytest.mark.skipif(sys.version_info < (3, 5), reason="LazyLoader was introduced in Python 3.5")
345+
@pytest.mark.subprocess(out="ddtrace imported\naccessing lazy module\nlazy loaded\n")
346+
def test_module_watchdog_no_lazy_force_load():
347+
"""Test that the module watchdog does not force-load lazy modules.
348+
349+
We use the LazyLoader to load a module lazily. On actual import, the module
350+
emits a print statement. We check that the timing of other print statements
351+
around the actual import is correct to ensure that the import of ddtrace is
352+
not forcing the lazy module to be loaded.
353+
"""
354+
import importlib.util
355+
import sys
356+
357+
def lazy_import(name):
358+
spec = importlib.util.find_spec(name)
359+
loader = importlib.util.LazyLoader(spec.loader)
360+
spec.loader = loader
361+
module = importlib.util.module_from_spec(spec)
362+
sys.modules[name] = module
363+
loader.exec_module(module)
364+
return module
365+
366+
lazy = lazy_import("tests.internal.lazy")
367+
368+
import ddtrace # noqa
369+
370+
print("ddtrace imported")
371+
372+
print("accessing lazy module")
373+
try:
374+
# This attribute access should cause the module to be loaded
375+
lazy.__spec__
376+
except AttributeError:
377+
pass

0 commit comments

Comments
 (0)