Skip to content

Commit 62aafc3

Browse files
committed
tests: add Python 3.9 compatibility
Add support for running integration tests on Python 3.9 through 3.14+ with minimal changes using modern Python features. Changes: - event.py: Add __future__ annotations import to enable modern type hint syntax (int | None) on Python 3.9, with fallback for @OverRide decorator (Python 3.12+) - test_config_hotreload.py: Handle both builtin TimeoutError (Python 3.11+) and concurrent.futures.TimeoutError (Python 3.9-3.10) - test_path_rmdir.py: Reverse event order for Python < 3.10 due to different shutil.rmtree deletion ordering This avoids using deprecated Union/Optional types while maintaining backward compatibility. Tested: 102 tests pass on Python 3.9.25 Assisted-by: Claude Code (claude-sonnet-4-5@20250929)
1 parent 3fe45f8 commit 62aafc3

3 files changed

Lines changed: 30 additions & 13 deletions

File tree

tests/event.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
from __future__ import annotations
2+
13
import os
24
from re import Pattern
35
import string
46
from enum import Enum
5-
from typing import Any, override
7+
from typing import Any
8+
9+
try:
10+
from typing import override
11+
except ImportError:
12+
def override(func):
13+
return func
614

715
from internalapi.sensor.collector_pb2 import ProcessSignal
816
from internalapi.sensor.sfa_pb2 import FileActivity

tests/test_config_hotreload.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
from time import sleep
3+
from concurrent.futures import TimeoutError as FuturesTimeoutError
34

45
from event import Event, EventType, Process
56

@@ -175,7 +176,7 @@ def test_no_paths_then_add(fact, fact_config, monitored_dir, server):
175176
e = Event(process=p, event_type=EventType.OPEN,
176177
file=fut, host_path=fut)
177178

178-
with pytest.raises(TimeoutError):
179+
with pytest.raises((TimeoutError, FuturesTimeoutError)):
179180
server.wait_events([e])
180181

181182
# Add paths back
@@ -216,7 +217,7 @@ def test_paths_then_remove(fact, fact_config, monitored_dir, server):
216217
f.write('This should be ignored')
217218
sleep(1)
218219

219-
with pytest.raises(TimeoutError):
220+
with pytest.raises((TimeoutError, FuturesTimeoutError)):
220221
server.wait_events([e])
221222

222223

tests/test_path_rmdir.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import shutil
3+
import sys
34

45
import pytest
56

@@ -17,7 +18,8 @@ def get_inode_removed_count(fact_config):
1718
Returns:
1819
The current value of host_scanner_scan{label="InodeRemoved"} metric.
1920
"""
20-
value = get_metric_value(fact_config, "host_scanner_scan", {"label": "InodeRemoved"})
21+
value = get_metric_value(fact_config, "host_scanner_scan", {
22+
"label": "InodeRemoved"})
2123
return int(value) if value is not None else 0
2224

2325

@@ -31,8 +33,10 @@ def get_kernel_rmdir_processed(fact_config):
3133
Returns:
3234
The difference between Total and Ignored kernel_path_rmdir_events.
3335
"""
34-
total_str = get_metric_value(fact_config, "kernel_path_rmdir_events", {"label": "Total"})
35-
ignored_str = get_metric_value(fact_config, "kernel_path_rmdir_events", {"label": "Ignored"})
36+
total_str = get_metric_value(
37+
fact_config, "kernel_path_rmdir_events", {"label": "Total"})
38+
ignored_str = get_metric_value(
39+
fact_config, "kernel_path_rmdir_events", {"label": "Ignored"})
3640

3741
total = int(total_str) if total_str is not None else 0
3842
ignored = int(ignored_str) if ignored_str is not None else 0
@@ -80,7 +84,7 @@ def test_rmdir_empty(monitored_dir, server, fact_config, dirname):
8084

8185
# File creation should be tracked
8286
e1 = Event(process=process, event_type=EventType.CREATION,
83-
file=test_file, host_path=test_file)
87+
file=test_file, host_path=test_file)
8488

8589
server.wait_events([e1])
8690

@@ -89,7 +93,7 @@ def test_rmdir_empty(monitored_dir, server, fact_config, dirname):
8993

9094
# File deletion should be tracked
9195
e2 = Event(process=process, event_type=EventType.UNLINK,
92-
file=test_file, host_path=test_file)
96+
file=test_file, host_path=test_file)
9397

9498
server.wait_events([e2])
9599

@@ -183,6 +187,10 @@ def test_rmdir_recursive(monitored_dir, server, fact_config):
183187
file=file3, host_path=file3),
184188
]
185189

190+
# Behavior of shutil.rmtree changed between python versions
191+
if sys.version_info < (3, 10):
192+
unlink_events.reverse()
193+
186194
server.wait_events(unlink_events)
187195

188196
# Check that all inodes and kernel events were tracked
@@ -244,7 +252,7 @@ def test_rmdir_ignored(monitored_dir, ignored_dir, server, fact_config):
244252

245253
# Monitored file creation should generate an event
246254
e1 = Event(process=process, event_type=EventType.CREATION,
247-
file=monitored_file, host_path=monitored_file)
255+
file=monitored_file, host_path=monitored_file)
248256

249257
server.wait_events([e1])
250258

@@ -301,7 +309,7 @@ def test_rmdir_with_parent_inode(monitored_dir, server, fact_config):
301309

302310
# Verify file creation is tracked
303311
e1 = Event(process=process, event_type=EventType.CREATION,
304-
file=test_file, host_path=test_file)
312+
file=test_file, host_path=test_file)
305313
server.wait_events([e1])
306314

307315
# Create another file at the root level (parent directory)
@@ -310,7 +318,7 @@ def test_rmdir_with_parent_inode(monitored_dir, server, fact_config):
310318
f.write('root content')
311319

312320
e2 = Event(process=process, event_type=EventType.CREATION,
313-
file=root_file, host_path=root_file)
321+
file=root_file, host_path=root_file)
314322
server.wait_events([e2])
315323

316324
# Remove the subdirectory and its contents
@@ -344,14 +352,14 @@ def test_rmdir_with_parent_inode(monitored_dir, server, fact_config):
344352
f.write('new content')
345353

346354
e4 = Event(process=process, event_type=EventType.CREATION,
347-
file=new_file, host_path=new_file)
355+
file=new_file, host_path=new_file)
348356
server.wait_events([e4])
349357

350358
# Remove the new file to clean up
351359
os.remove(new_file)
352360

353361
e5 = Event(process=process, event_type=EventType.UNLINK,
354-
file=new_file, host_path=new_file)
362+
file=new_file, host_path=new_file)
355363
server.wait_events([e5])
356364

357365
# Final metric check: should be 3 total inodes (test_file, subdir, new_file)

0 commit comments

Comments
 (0)