Skip to content

Commit 1e014ec

Browse files
committed
split stubs and avoid import cycles
1 parent ef3713e commit 1e014ec

File tree

8 files changed

+180
-161
lines changed

8 files changed

+180
-161
lines changed

ddtrace/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from .internal._instrumentation_enabled import _INSTRUMENTATION_ENABLED
1616

17-
from .internal._stubs_core import get_config
17+
from .internal._stubs_config import get_config
1818

1919
config = get_config()
2020

ddtrace/_logger.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import Optional
33

44
from ddtrace.internal._instrumentation_enabled import _INSTRUMENTATION_ENABLED
5-
from ddtrace.internal._stubs_core import logging
5+
from ddtrace.internal._stubs_logging import logging
66
from ddtrace.internal.utils.formats import asbool
77

88

ddtrace/_monkey.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import Union
77

88
from ddtrace.internal._instrumentation_enabled import _INSTRUMENTATION_ENABLED
9-
from ddtrace.internal._stubs_core import get_config
9+
from ddtrace.internal._stubs_config import get_config
1010
from ddtrace.internal._stubs_core import when_imported
1111
from ddtrace.internal._stubs_vendor import TELEMETRY_NAMESPACE
1212
from ddtrace.internal._stubs_vendor import DDTraceDeprecationWarning

ddtrace/internal/_stubs_config.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""
2+
Configuration stubs that don't have circular import dependencies.
3+
These are the config-related stubs needed when instrumentation is disabled.
4+
"""
5+
6+
from typing import Dict
7+
8+
from ._instrumentation_enabled import _INSTRUMENTATION_ENABLED
9+
10+
11+
# Configuration stubs - comprehensive version that implements ConfigProtocol
12+
class _NullConfig:
13+
# Implement all the Protocol attributes with sensible defaults
14+
_data_streams_enabled: bool = False
15+
_from_endpoint: Dict = {}
16+
_remote_config_enabled: bool = False
17+
_sca_enabled: bool = False
18+
_trace_safe_instrumentation_enabled: bool = False
19+
_modules_to_report = None
20+
_report_handled_errors = None
21+
_configured_modules = None
22+
_instrument_user_code: bool = False
23+
_instrument_third_party_code: bool = False
24+
_instrument_all: bool = False
25+
_stacktrace_resolver = None
26+
_enabled: bool = False
27+
_http_tag_query_string: bool = False
28+
_health_metrics_enabled: bool = False
29+
_trace_writer_interval_seconds: float = 1.0
30+
_trace_writer_connection_reuse: bool = False
31+
_trace_writer_log_err_payload: bool = False
32+
_trace_api: str = "v0.5"
33+
_trace_writer_buffer_size: int = 1000
34+
_trace_writer_payload_size: int = 1000
35+
_http = None
36+
_logs_injection: bool = False
37+
_dd_site = None
38+
_dd_api_key = None
39+
_llmobs_ml_app = None
40+
_llmobs_instrumented_proxy_urls = None
41+
_llmobs_agentless_enabled = False
42+
_trace_compute_stats: bool = False
43+
_tracing_enabled: bool = False
44+
45+
# Common properties
46+
service = None
47+
env = None
48+
version = None
49+
tags: Dict = {}
50+
service_mapping: Dict = {}
51+
52+
def __getattr__(self, name):
53+
# Handle dynamic attributes and integration configs
54+
if name.endswith("_enabled"):
55+
return False
56+
if name.endswith("_timeout"):
57+
return 0
58+
if name.startswith("_") and "interval" in name:
59+
return 1.0
60+
if name.startswith("_") and ("size" in name or "limit" in name):
61+
return 1000
62+
return False
63+
64+
def _add_extra_service(self, service_name: str) -> None:
65+
pass # No-op for null config
66+
67+
def _get_extra_services(self):
68+
return set()
69+
70+
71+
# Function to get the appropriate config instance based on instrumentation status
72+
def get_config():
73+
"""Get the appropriate config instance - real Config when instrumentation enabled, _NullConfig otherwise."""
74+
if _INSTRUMENTATION_ENABLED:
75+
# Import the real config when instrumentation is enabled (lazy import to avoid circular imports)
76+
from ddtrace.settings._config import config
77+
78+
return config
79+
else:
80+
# Use the null config when instrumentation is disabled
81+
return _NullConfig()
82+
83+
84+
# Export the config stubs
85+
__all__ = ["_NullConfig", "get_config"]

ddtrace/internal/_stubs_core.py

Lines changed: 2 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,17 @@
11
"""
22
Core stubs that don't have circular import dependencies.
3-
These are the basic stubs needed early in the import process.
3+
These are the wrapt-related stubs needed early in the import process.
44
"""
55

6-
from typing import Dict
7-
from typing import List
8-
96
from ._instrumentation_enabled import _INSTRUMENTATION_ENABLED
107

118

129
if _INSTRUMENTATION_ENABLED:
13-
import logging
14-
1510
import wrapt
1611
from wrapt.importer import when_imported
1712
else:
1813
# Provide minimal stubs when instrumentation is disabled
1914

20-
class logging: # type: ignore[no-redef]
21-
DEBUG = 10
22-
INFO = 20
23-
WARNING = 30
24-
ERROR = 40
25-
CRITICAL = 50
26-
27-
class Logger:
28-
def debug(self, *args, **kwargs):
29-
pass
30-
31-
def info(self, *args, **kwargs):
32-
pass
33-
34-
def warning(self, *args, **kwargs):
35-
pass
36-
37-
def error(self, *args, **kwargs):
38-
pass
39-
40-
def critical(self, *args, **kwargs):
41-
pass
42-
43-
def setLevel(self, level):
44-
pass
45-
46-
def addHandler(self, handler):
47-
pass
48-
49-
def addFilter(self, _filter):
50-
pass
51-
52-
def isEnabledFor(self, level):
53-
return False
54-
55-
handlers: List = []
56-
57-
class LogRecord:
58-
def __init__(self, *args, **kwargs):
59-
self.name = ""
60-
self.msg = ""
61-
self.pathname = ""
62-
self.lineno = 0
63-
self.levelno = 0
64-
65-
@staticmethod
66-
def getLogger(name):
67-
return logging.Logger()
68-
69-
class StreamHandler:
70-
def __init__(self):
71-
pass
72-
73-
def setLevel(self, level):
74-
pass
75-
76-
def setFormatter(self, formatter):
77-
pass
78-
79-
def set_name(self, name):
80-
pass
81-
82-
class Formatter:
83-
def __init__(self, fmt):
84-
pass
85-
86-
@staticmethod
87-
def warning(msg, *args):
88-
pass
89-
9015
class wrapt: # type: ignore[no-redef]
9116
class ObjectProxy:
9217
def __init__(self, wrapped):
@@ -114,78 +39,5 @@ def when_imported(x):
11439
return lambda y: None
11540

11641

117-
# Configuration stubs - comprehensive version that implements ConfigProtocol
118-
class _NullConfig:
119-
# Implement all the Protocol attributes with sensible defaults
120-
_data_streams_enabled: bool = False
121-
_from_endpoint: Dict = {}
122-
_remote_config_enabled: bool = False
123-
_sca_enabled: bool = False
124-
_trace_safe_instrumentation_enabled: bool = False
125-
_modules_to_report = None
126-
_report_handled_errors = None
127-
_configured_modules = None
128-
_instrument_user_code: bool = False
129-
_instrument_third_party_code: bool = False
130-
_instrument_all: bool = False
131-
_stacktrace_resolver = None
132-
_enabled: bool = False
133-
_http_tag_query_string: bool = False
134-
_health_metrics_enabled: bool = False
135-
_trace_writer_interval_seconds: float = 1.0
136-
_trace_writer_connection_reuse: bool = False
137-
_trace_writer_log_err_payload: bool = False
138-
_trace_api: str = "v0.5"
139-
_trace_writer_buffer_size: int = 1000
140-
_trace_writer_payload_size: int = 1000
141-
_http = None
142-
_logs_injection: bool = False
143-
_dd_site = None
144-
_dd_api_key = None
145-
_llmobs_ml_app = None
146-
_llmobs_instrumented_proxy_urls = None
147-
_llmobs_agentless_enabled = False
148-
_trace_compute_stats: bool = False
149-
_tracing_enabled: bool = False
150-
151-
# Common properties
152-
service = None
153-
env = None
154-
version = None
155-
tags: Dict = {}
156-
service_mapping: Dict = {}
157-
158-
def __getattr__(self, name):
159-
# Handle dynamic attributes and integration configs
160-
if name.endswith("_enabled"):
161-
return False
162-
if name.endswith("_timeout"):
163-
return 0
164-
if name.startswith("_") and "interval" in name:
165-
return 1.0
166-
if name.startswith("_") and ("size" in name or "limit" in name):
167-
return 1000
168-
return False
169-
170-
def _add_extra_service(self, service_name: str) -> None:
171-
pass # No-op for null config
172-
173-
def _get_extra_services(self):
174-
return set()
175-
176-
177-
# Function to get the appropriate config instance based on instrumentation status
178-
def get_config():
179-
"""Get the appropriate config instance - real Config when instrumentation enabled, _NullConfig otherwise."""
180-
if _INSTRUMENTATION_ENABLED:
181-
# Import the real config when instrumentation is enabled (lazy import to avoid circular imports)
182-
from ddtrace.settings._config import config
183-
184-
return config
185-
else:
186-
# Use the null config when instrumentation is disabled
187-
return _NullConfig()
188-
189-
19042
# Export the core stubs
191-
__all__ = ["logging", "wrapt", "_NullConfig", "when_imported", "get_config"]
43+
__all__ = ["wrapt", "when_imported"]

ddtrace/internal/_stubs_logging.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""
2+
Logging stubs that don't have circular import dependencies.
3+
These are the logging-related stubs needed when instrumentation is disabled.
4+
"""
5+
6+
from typing import List
7+
8+
from ._instrumentation_enabled import _INSTRUMENTATION_ENABLED
9+
10+
11+
if _INSTRUMENTATION_ENABLED:
12+
import logging
13+
else:
14+
# Provide minimal stubs when instrumentation is disabled
15+
16+
class logging: # type: ignore[no-redef]
17+
DEBUG = 10
18+
INFO = 20
19+
WARNING = 30
20+
ERROR = 40
21+
CRITICAL = 50
22+
23+
class Logger:
24+
def debug(self, *args, **kwargs):
25+
pass
26+
27+
def info(self, *args, **kwargs):
28+
pass
29+
30+
def warning(self, *args, **kwargs):
31+
pass
32+
33+
def error(self, *args, **kwargs):
34+
pass
35+
36+
def critical(self, *args, **kwargs):
37+
pass
38+
39+
def setLevel(self, level):
40+
pass
41+
42+
def addHandler(self, handler):
43+
pass
44+
45+
def addFilter(self, _filter):
46+
pass
47+
48+
def isEnabledFor(self, level):
49+
return False
50+
51+
handlers: List = []
52+
53+
class LogRecord:
54+
def __init__(self, *args, **kwargs):
55+
self.name = ""
56+
self.msg = ""
57+
self.pathname = ""
58+
self.lineno = 0
59+
self.levelno = 0
60+
61+
@staticmethod
62+
def getLogger(name):
63+
return logging.Logger()
64+
65+
class StreamHandler:
66+
def __init__(self):
67+
pass
68+
69+
def setLevel(self, level):
70+
pass
71+
72+
def setFormatter(self, formatter):
73+
pass
74+
75+
def set_name(self, name):
76+
pass
77+
78+
class Formatter:
79+
def __init__(self, fmt):
80+
pass
81+
82+
@staticmethod
83+
def warning(msg, *args):
84+
pass
85+
86+
87+
# Export the logging stubs
88+
__all__ = ["logging"]

ddtrace/internal/logger.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from typing import Tuple
4343
from typing import Union
4444

45-
from ._stubs_core import logging
45+
from ._stubs_logging import logging
4646

4747

4848
SECOND = 1

0 commit comments

Comments
 (0)