Skip to content

Commit b8b536d

Browse files
committed
use helper for code path resolution
1 parent f02d7b7 commit b8b536d

File tree

5 files changed

+21
-9
lines changed

5 files changed

+21
-9
lines changed

ddtrace/debugging/_function/discovery.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from collections import defaultdict
22
from collections import deque
3-
from pathlib import Path
43
from types import CodeType
54
from types import FunctionType
65
from types import ModuleType
@@ -24,6 +23,7 @@
2423
from ddtrace.internal.utils.inspection import collect_code_objects
2524
from ddtrace.internal.utils.inspection import functions_for_code
2625
from ddtrace.internal.utils.inspection import linenos
26+
from ddtrace.internal.utils.inspection import resolved_code_origin
2727
from ddtrace.internal.utils.inspection import undecorated
2828

2929

@@ -209,7 +209,7 @@ def _collect_functions(module: ModuleType) -> Dict[str, _FunctionCodePair]:
209209

210210
for name in (k, local_name) if isinstance(k, str) and k != local_name else (local_name,):
211211
fullname = ".".join((c.__fullname__, name)) if c.__fullname__ else name
212-
if fullname not in functions or Path(code.co_filename).resolve() == path:
212+
if fullname not in functions or resolved_code_origin(code) == path:
213213
# Give precedence to code objects from the module and
214214
# try to retrieve any potentially decorated function so
215215
# that we don't end up returning the decorator function
@@ -285,7 +285,7 @@ def __init__(self, module: ModuleType) -> None:
285285

286286
if (
287287
function not in seen_functions
288-
and Path(cast(FunctionType, function).__code__.co_filename).resolve() == module_path
288+
and resolved_code_origin(cast(FunctionType, function).__code__) == module_path
289289
):
290290
# We only map line numbers for functions that actually belong to
291291
# the module.
@@ -342,7 +342,7 @@ def _resolve_pair(self, pair: _FunctionCodePair, fullname: str) -> FullyNamedFun
342342

343343
code = pair.code
344344
assert code is not None # nosec
345-
f = undecorated(cast(FunctionType, target), cast(str, part), Path(code.co_filename).resolve())
345+
f = undecorated(cast(FunctionType, target), cast(str, part), resolved_code_origin(code))
346346
if not (isinstance(f, FunctionType) and f.__code__ is code):
347347
raise e
348348

ddtrace/debugging/_origin/span.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def from_frame(cls, frame: FrameType) -> "ExitSpanProbe":
102102
ExitSpanProbe,
103103
cls.build(
104104
name=code.co_qualname if sys.version_info >= (3, 11) else code.co_name, # type: ignore[attr-defined]
105-
filename=str(Path(code.co_filename).resolve()),
105+
filename=str(Path(code.co_filename)),
106106
line=frame.f_lineno,
107107
),
108108
)

ddtrace/internal/coverage/code.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from ddtrace.internal.packages import purelib_path
2121
from ddtrace.internal.packages import stdlib_path
2222
from ddtrace.internal.test_visibility.coverage_lines import CoverageLines
23+
from ddtrace.internal.utils.inspection import resolved_code_origin
2324

2425

2526
log = get_logger(__name__)
@@ -317,7 +318,7 @@ def transform(self, code: CodeType, _module: ModuleType) -> CodeType:
317318
if _module is None:
318319
return code
319320

320-
code_path = Path(code.co_filename).resolve()
321+
code_path = resolved_code_origin(code)
321322

322323
if not any(code_path.is_relative_to(include_path) for include_path in self._include_paths):
323324
# Not a code object we want to instrument

ddtrace/internal/symbol_db/symbols.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from ddtrace.internal.utils.http import connector
3939
from ddtrace.internal.utils.http import multipart
4040
from ddtrace.internal.utils.inspection import linenos
41+
from ddtrace.internal.utils.inspection import resolved_code_origin
4142
from ddtrace.internal.utils.inspection import undecorated
4243
from ddtrace.settings._agent import config as agent_config
4344
from ddtrace.settings.symbol_db import config as symdb_config
@@ -323,7 +324,7 @@ def _(cls, code: CodeType, data: ScopeData, recursive: bool = True):
323324
return None
324325
data.seen.add(code_id)
325326

326-
if Path(code.co_filename).resolve() != data.origin:
327+
if (code_origin := resolved_code_origin(code)) != data.origin:
327328
# Comes from another module.
328329
return None
329330

@@ -337,7 +338,7 @@ def _(cls, code: CodeType, data: ScopeData, recursive: bool = True):
337338
return Scope(
338339
scope_type=ScopeType.CLOSURE, # DEV: Not in the sense of a Python closure.
339340
name=code.co_name,
340-
source_file=str(Path(code.co_filename).resolve()),
341+
source_file=str(code_origin),
341342
start_line=start_line,
342343
end_line=end_line,
343344
symbols=Symbol.from_code(code),

ddtrace/internal/utils/inspection.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from typing import cast
1414

1515
from ddtrace.internal.safety import _isinstance
16+
from ddtrace.internal.utils.cache import cached
1617

1718

1819
@singledispatch
@@ -31,14 +32,23 @@ def _(f: FunctionType) -> Set[int]:
3132
return linenos(f.__code__)
3233

3334

35+
@cached(maxsize=4 << 10)
36+
def _filename_to_resolved_path(filename: str) -> Path:
37+
return Path(filename).resolve()
38+
39+
40+
def resolved_code_origin(code: CodeType) -> Path:
41+
return _filename_to_resolved_path(code.co_filename)
42+
43+
3444
def undecorated(f: FunctionType, name: str, path: Path) -> FunctionType:
3545
# Find the original function object from a decorated function. We use the
3646
# expected function name to guide the search and pick the correct function.
3747
# The recursion is needed in case of multiple decorators. We make it BFS
3848
# to find the function as soon as possible.
3949

4050
def match(g):
41-
return g.__code__.co_name == name and Path(g.__code__.co_filename).resolve() == path
51+
return g.__code__.co_name == name and resolved_code_origin(g.__code__) == path
4252

4353
if _isinstance(f, FunctionType) and match(f):
4454
return f

0 commit comments

Comments
 (0)