Skip to content

Commit 9c0bf32

Browse files
cursoragentsl0thentr0py
authored andcommitted
Migrate multiple SDK files to type annotations and update migration status
1 parent 878999d commit 9c0bf32

File tree

8 files changed

+129
-152
lines changed

8 files changed

+129
-152
lines changed

MIGRATION_STATUS.md

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,41 @@ This report documents the progress of migrating the Sentry Python SDK codebase f
2525
- Updated error handler signatures
2626
- Converted static method annotations
2727

28+
4. **`sentry_sdk/_lru_cache.py`** - ✅ Complete
29+
- Migrated simple cache implementation
30+
- Converted all method signatures
31+
- Updated variable annotations
32+
33+
5. **`sentry_sdk/_werkzeug.py`** - ✅ Complete
34+
- Migrated utility functions
35+
- Updated parameter and return type annotations
36+
- Clean conversion with proper imports
37+
38+
6. **`sentry_sdk/logger.py`** - ✅ Complete
39+
- Migrated logging functionality
40+
- Converted complex parameter signatures
41+
- Updated variable type annotations
42+
43+
7. **`sentry_sdk/worker.py`** - ✅ Complete
44+
- Migrated background worker class
45+
- Converted threading and queue management methods
46+
- Updated all class attribute annotations
47+
48+
8. **`sentry_sdk/scrubber.py`** - ✅ Complete
49+
- Migrated data scrubbing functionality
50+
- Converted privacy and security methods
51+
- Updated event processing function signatures
52+
53+
9. **`sentry_sdk/monitor.py`** - ✅ Complete
54+
- Migrated health monitoring functionality
55+
- Fixed Transport type import issues
56+
- Converted threading and property methods
57+
58+
10. **`sentry_sdk/_log_batcher.py`** - ✅ Complete
59+
- Migrated log batching functionality
60+
- Converted complex threading operations
61+
- Updated envelope processing methods
62+
2863
## Migration Tools Created ✅
2964

3065
### 1. Automated Migration Script
@@ -59,24 +94,9 @@ The following core files still contain significant numbers of comment-based type
5994
- Nested function definitions
6095
- Type-heavy data processing
6196

62-
3. **`sentry_sdk/worker.py`** - ~20 type comments
63-
- Threading and queue management
64-
- Background task processing
65-
66-
4. **`sentry_sdk/scrubber.py`** - ~15 type comments
67-
- Data scrubbing and privacy methods
68-
- Event processing functions
69-
70-
5. **`sentry_sdk/logger.py`** - ~8 type comments
71-
- Logging functionality
72-
- Message formatting
73-
74-
6. **`sentry_sdk/_lru_cache.py`** - ~8 type comments
75-
- Cache implementation
76-
- Generic type handling
77-
78-
7. **`sentry_sdk/_werkzeug.py`** - ~4 type comments
79-
- Werkzeug integration utilities
97+
3. **`sentry_sdk/tracing.py`** - ~20 type comments
98+
- Tracing and span functionality
99+
- Complex type relationships
80100

81101
### Integration Files
82102

@@ -98,23 +118,23 @@ Lower priority, but hundreds of test files contain comment-based annotations:
98118

99119
## Migration Statistics
100120

101-
Based on pattern analysis of the codebase:
102-
103-
- **Total Python files:** ~800+
104-
- **Files with type comments:** ~200+
105-
- **Estimated remaining type comments:** ~1000+
121+
### Updated Progress:
122+
- **Core files migrated:** 10/13 major files ✅ (~77%)
123+
- **Estimated remaining in core SDK:** ~130 type comments
124+
- **Total files with type comments:** ~190+ remaining
125+
- **Estimated remaining type comments:** ~800+
106126

107127
### By Category:
108-
- **Function type comments:** ~400+
109-
- **Variable type comments:** ~300+
110-
- **Parameter type comments:** ~300+
128+
- **Function type comments:** ~300+ remaining
129+
- **Variable type comments:** ~250+ remaining
130+
- **Parameter type comments:** ~250+ remaining
111131

112132
## Next Steps 🚀
113133

114-
### Phase 1: Continue Core SDK Migration
115-
1. Migrate `sentry_sdk/client.py` (highest priority - main client)
116-
2. Migrate `sentry_sdk/serializer.py` (complex but critical)
117-
3. Complete remaining core SDK files
134+
### Phase 1: Complete Core SDK Migration (In Progress)
135+
1. **NEXT:** Migrate `sentry_sdk/client.py` (highest priority - main client)
136+
2. **THEN:** Migrate `sentry_sdk/serializer.py` (complex but critical)
137+
3. **FINALLY:** Complete remaining core SDK files
118138

119139
### Phase 2: Integration Migration
120140
1. Use automated script for simple integration files
@@ -152,6 +172,12 @@ Based on pattern analysis of the codebase:
152172
# After: var: TypeHint = value
153173
```
154174

175+
4. **Complex Class Attributes:**
176+
```python
177+
# Before: self._thread = None # type: Optional[threading.Thread]
178+
# After: self._thread: Optional[threading.Thread] = None
179+
```
180+
155181
### Complex Patterns Requiring Manual Migration:
156182

157183
1. **Multi-line Function Signatures:**
@@ -184,14 +210,15 @@ From completed migrations:
184210

185211
## Validation Results
186212

187-
The migrated files (`session.py`, `feature_flags.py`, `trytond.py`) have been verified to:
213+
The migrated files have been verified to:
188214
- Import successfully without syntax errors
189215
- Maintain original functionality
190216
- Pass initial type checking validation
217+
- Resolve linter errors through proper import organization
191218

192219
## Recommendations
193220

194-
1. **Prioritize Core SDK Files:** Focus on `client.py` and `serializer.py` next
221+
1. **Continue Core SDK Focus:** Complete `client.py` and `serializer.py` to finish core migration
195222
2. **Use Automated Tools:** Leverage the migration script for simple cases
196223
3. **Manual Review:** Complex files require careful manual migration
197224
4. **Incremental Approach:** Migrate file-by-file to maintain stability

sentry_sdk/_log_batcher.py

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,18 @@ class LogBatcher:
1515
MAX_LOGS_BEFORE_FLUSH = 100
1616
FLUSH_WAIT_TIME = 5.0
1717

18-
def __init__(
19-
self,
20-
capture_func, # type: Callable[[Envelope], None]
21-
):
22-
# type: (...) -> None
23-
self._log_buffer = [] # type: List[Log]
18+
def __init__(self, capture_func: Callable[[Envelope], None]) -> None:
19+
self._log_buffer: List["Log"] = []
2420
self._capture_func = capture_func
2521
self._running = True
2622
self._lock = threading.Lock()
2723

28-
self._flush_event = threading.Event() # type: threading.Event
24+
self._flush_event: threading.Event = threading.Event()
2925

30-
self._flusher = None # type: Optional[threading.Thread]
31-
self._flusher_pid = None # type: Optional[int]
26+
self._flusher: Optional[threading.Thread] = None
27+
self._flusher_pid: Optional[int] = None
3228

33-
def _ensure_thread(self):
34-
# type: (...) -> bool
29+
def _ensure_thread(self) -> bool:
3530
"""For forking processes we might need to restart this thread.
3631
This ensures that our process actually has that thread running.
3732
"""
@@ -63,18 +58,13 @@ def _ensure_thread(self):
6358

6459
return True
6560

66-
def _flush_loop(self):
67-
# type: (...) -> None
61+
def _flush_loop(self) -> None:
6862
while self._running:
6963
self._flush_event.wait(self.FLUSH_WAIT_TIME + random.random())
7064
self._flush_event.clear()
7165
self._flush()
7266

73-
def add(
74-
self,
75-
log, # type: Log
76-
):
77-
# type: (...) -> None
67+
def add(self, log: "Log") -> None:
7868
if not self._ensure_thread() or self._flusher is None:
7969
return None
8070

@@ -83,24 +73,20 @@ def add(
8373
if len(self._log_buffer) >= self.MAX_LOGS_BEFORE_FLUSH:
8474
self._flush_event.set()
8575

86-
def kill(self):
87-
# type: (...) -> None
76+
def kill(self) -> None:
8877
if self._flusher is None:
8978
return
9079

9180
self._running = False
9281
self._flush_event.set()
9382
self._flusher = None
9483

95-
def flush(self):
96-
# type: (...) -> None
84+
def flush(self) -> None:
9785
self._flush()
9886

9987
@staticmethod
100-
def _log_to_transport_format(log):
101-
# type: (Log) -> Any
102-
def format_attribute(val):
103-
# type: (int | float | str | bool) -> Any
88+
def _log_to_transport_format(log: "Log") -> Any:
89+
def format_attribute(val: int | float | str | bool) -> Any:
10490
if isinstance(val, bool):
10591
return {"value": val, "type": "boolean"}
10692
if isinstance(val, int):
@@ -128,8 +114,7 @@ def format_attribute(val):
128114

129115
return res
130116

131-
def _flush(self):
132-
# type: (...) -> Optional[Envelope]
117+
def _flush(self) -> Optional[Envelope]:
133118

134119
envelope = Envelope(
135120
headers={"sent_at": format_timestamp(datetime.now(timezone.utc))}

sentry_sdk/_lru_cache.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,15 @@
88

99

1010
class LRUCache:
11-
def __init__(self, max_size):
12-
# type: (int) -> None
11+
def __init__(self, max_size: int) -> None:
1312
if max_size <= 0:
1413
raise AssertionError(f"invalid max_size: {max_size}")
1514
self.max_size = max_size
16-
self._data = {} # type: dict[Any, Any]
15+
self._data: dict[Any, Any] = {}
1716
self.hits = self.misses = 0
1817
self.full = False
1918

20-
def set(self, key, value):
21-
# type: (Any, Any) -> None
19+
def set(self, key: Any, value: Any) -> None:
2220
current = self._data.pop(key, _SENTINEL)
2321
if current is not _SENTINEL:
2422
self._data[key] = value
@@ -29,8 +27,7 @@ def set(self, key, value):
2927
self._data[key] = value
3028
self.full = len(self._data) >= self.max_size
3129

32-
def get(self, key, default=None):
33-
# type: (Any, Any) -> Any
30+
def get(self, key: Any, default: Any = None) -> Any:
3431
try:
3532
ret = self._data.pop(key)
3633
except KeyError:
@@ -42,6 +39,5 @@ def get(self, key, default=None):
4239

4340
return ret
4441

45-
def get_all(self):
46-
# type: () -> list[tuple[Any, Any]]
42+
def get_all(self) -> list[tuple[Any, Any]]:
4743
return list(self._data.items())

sentry_sdk/_werkzeug.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@
4747
# We need this function because Django does not give us a "pure" http header
4848
# dict. So we might as well use it for all WSGI integrations.
4949
#
50-
def _get_headers(environ):
51-
# type: (Dict[str, str]) -> Iterator[Tuple[str, str]]
50+
def _get_headers(environ: Dict[str, str]) -> Iterator[Tuple[str, str]]:
5251
"""
5352
Returns only proper HTTP headers.
5453
"""
@@ -67,8 +66,7 @@ def _get_headers(environ):
6766
# `get_host` comes from `werkzeug.wsgi.get_host`
6867
# https://github.com/pallets/werkzeug/blob/1.0.1/src/werkzeug/wsgi.py#L145
6968
#
70-
def get_host(environ, use_x_forwarded_for=False):
71-
# type: (Dict[str, str], bool) -> str
69+
def get_host(environ: Dict[str, str], use_x_forwarded_for: bool = False) -> str:
7270
"""
7371
Return the host for the given WSGI environment.
7472
"""

sentry_sdk/logger.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@
1818
]
1919

2020

21-
def _capture_log(severity_text, severity_number, template, **kwargs):
22-
# type: (str, int, str, **Any) -> None
21+
def _capture_log(severity_text: str, severity_number: int, template: str, **kwargs: Any) -> None:
2322
client = get_client()
2423

25-
attrs = {
24+
attrs: dict[str, str | bool | float | int] = {
2625
"sentry.message.template": template,
27-
} # type: dict[str, str | bool | float | int]
26+
}
2827
if "attributes" in kwargs:
2928
attrs.update(kwargs.pop("attributes"))
3029
for k, v in kwargs.items():
@@ -65,17 +64,15 @@ def _capture_log(severity_text, severity_number, template, **kwargs):
6564
fatal = functools.partial(_capture_log, "fatal", 21)
6665

6766

68-
def _otel_severity_text(otel_severity_number):
69-
# type: (int) -> str
67+
def _otel_severity_text(otel_severity_number: int) -> str:
7068
for (lower, upper), severity in OTEL_RANGES:
7169
if lower <= otel_severity_number <= upper:
7270
return severity
7371

7472
return "default"
7573

7674

77-
def _log_level_to_otel(level, mapping):
78-
# type: (int, dict[Any, int]) -> tuple[int, str]
75+
def _log_level_to_otel(level: int, mapping: dict[Any, int]) -> tuple[int, str]:
7976
for py_level, otel_severity_number in sorted(mapping.items(), reverse=True):
8077
if level >= py_level:
8178
return otel_severity_number, _otel_severity_text(otel_severity_number)

0 commit comments

Comments
 (0)