Skip to content

Commit e3dff23

Browse files
gh-152548: Move per-test imports into the test methods in test_audit
Keep at module level only what the old audit-tests.py had there (os, sys, unittest.mock) plus the test framework (unittest, support); import the modules under test and the helpers (import_helper, os_helper, script_helper, textwrap) inside the methods that use them. For the optional modules a requires_module() decorator runs the import_helper check in the parent process, so a missing module skips the test without first spawning an @isolated() subprocess. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 9b51235 commit e3dff23

1 file changed

Lines changed: 42 additions & 14 deletions

File tree

Lib/test/test_audit.py

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,8 @@
99

1010
import os
1111
import sys
12-
import textwrap
1312
import unittest
1413
from test import support
15-
from test.support import import_helper
16-
from test.support import os_helper
17-
from test.support import script_helper
1814
from unittest.mock import ANY
1915

2016

@@ -55,6 +51,24 @@ def __call__(self, event, args):
5551
raise self.exc_type("saw event " + event)
5652

5753

54+
def requires_module(name):
55+
"""Skip the test, in the parent process, if module *name* is unavailable.
56+
57+
Checking here means a missing module skips the test without first spawning
58+
the @isolated() subprocess.
59+
"""
60+
import functools
61+
62+
def decorator(func):
63+
@functools.wraps(func)
64+
def wrapper(self):
65+
from test.support import import_helper
66+
import_helper.import_module(name)
67+
return func(self)
68+
return wrapper
69+
return decorator
70+
71+
5872
class AuditTest(unittest.TestCase):
5973
maxDiff = None
6074

@@ -87,6 +101,7 @@ def test_block_add_hook_baseexception(self):
87101
@support.isolated()
88102
def test_marshal(self):
89103
import marshal
104+
from test.support import os_helper
90105

91106
o = ("a", "b", "c", 1, 2, 3)
92107
payload = marshal.dumps(o)
@@ -169,6 +184,8 @@ class C(A):
169184

170185
@support.isolated()
171186
def test_open(self):
187+
from test.support import os_helper
188+
172189
testfn = os_helper.TESTFN
173190

174191
# SSLContext.load_dh_params uses Py_fopen() rather than normal open()
@@ -304,9 +321,9 @@ def test_mmap(self):
304321
mmap.mmap(-1, 8)
305322
self.assertEqual(hook.seen[0][1][:2], (-1, 8))
306323

324+
@requires_module("ctypes")
307325
@support.isolated()
308326
def test_ctypes_call_function(self):
309-
import_helper.import_module("ctypes")
310327
import ctypes
311328
import _ctypes
312329

@@ -330,9 +347,9 @@ def test_ctypes_call_function(self):
330347
self.assertIn("ctypes.call_function", hook.seen_events)
331348
self.assertIn("ctypes.string_at", hook.seen_events)
332349

350+
@requires_module("_posixsubprocess")
333351
@support.isolated()
334352
def test_posixsubprocess(self):
335-
import_helper.import_module("_posixsubprocess")
336353
import multiprocessing.util
337354

338355
exe = b"xxx"
@@ -344,6 +361,9 @@ def test_posixsubprocess(self):
344361

345362
@support.requires_subprocess()
346363
def test_excepthook(self):
364+
import textwrap
365+
from test.support import script_helper
366+
347367
# The "sys.excepthook" audit event fires only for an exception that goes
348368
# uncaught to the top level of the interpreter, so this case cannot use
349369
# @isolated() (whose test body runs under unittest, which catches the
@@ -375,9 +395,10 @@ def hook(event, args):
375395
stderr.decode(),
376396
)
377397

398+
@requires_module("_testcapi")
378399
@support.isolated()
379400
def test_unraisablehook(self):
380-
_testcapi = import_helper.import_module("_testcapi")
401+
import _testcapi
381402

382403
def unraisablehook(hookargs):
383404
pass
@@ -401,9 +422,10 @@ def hook(event, args):
401422
self.assertEqual(args[1].err_msg,
402423
"Exception ignored for audit hook test")
403424

425+
@requires_module("winreg")
404426
@support.isolated()
405427
def test_winreg(self):
406-
winreg = import_helper.import_module("winreg")
428+
import winreg
407429

408430
events = []
409431

@@ -428,6 +450,7 @@ def hook(event, args):
428450
self.assertEqual(events[3], ("winreg.EnumKey", (hkey, 10000)))
429451
self.assertEqual(events[4], ("winreg.PyHKEY.Detach", (hkey,)))
430452

453+
@requires_module("socket")
431454
@support.isolated()
432455
def test_socket(self):
433456
import socket
@@ -482,9 +505,10 @@ def hook(event, args):
482505
["gc.get_objects", "gc.get_referrers", "gc.get_referents"])
483506

484507
@support.requires_resource('network')
508+
@requires_module("http.client")
485509
@support.isolated()
486510
def test_http(self):
487-
http_client = import_helper.import_module("http.client")
511+
import http.client
488512

489513
events = []
490514

@@ -494,7 +518,7 @@ def hook(event, args):
494518

495519
sys.addaudithook(hook)
496520

497-
conn = http_client.HTTPConnection('www.python.org')
521+
conn = http.client.HTTPConnection('www.python.org')
498522
sent = True
499523
try:
500524
conn.request('GET', '/')
@@ -509,9 +533,10 @@ def hook(event, args):
509533
self.assertEqual(events[1][0], "http.client.send")
510534
self.assertIn(b'HTTP', events[1][1][0])
511535

536+
@requires_module("sqlite3")
512537
@support.isolated()
513538
def test_sqlite3(self):
514-
sqlite3 = import_helper.import_module("sqlite3")
539+
import sqlite3
515540

516541
events = []
517542

@@ -608,9 +633,10 @@ def __call__(self):
608633
],
609634
)
610635

636+
@requires_module("_wmi")
611637
@support.isolated()
612638
def test_wmi_exec_query(self):
613-
_wmi = import_helper.import_module("_wmi")
639+
import _wmi
614640

615641
events = []
616642

@@ -632,9 +658,10 @@ def hook(event, args):
632658
self.assertEqual(events[0][1][0],
633659
"SELECT * FROM Win32_OperatingSystem")
634660

661+
@requires_module("syslog")
635662
@support.isolated()
636663
def test_syslog(self):
637-
syslog = import_helper.import_module("syslog")
664+
import syslog
638665

639666
events = []
640667

@@ -729,9 +756,10 @@ def hook(event, args):
729756
self.assertEqual(
730757
events, [("sys.monitoring.register_callback", (None,))])
731758

759+
@requires_module("_winapi")
732760
@support.isolated()
733761
def test_winapi_createnamedpipe(self):
734-
_winapi = import_helper.import_module("_winapi")
762+
import _winapi
735763

736764
pipe_name = r"\\.\pipe\LOCAL\test_winapi_createnamed_pipe"
737765

0 commit comments

Comments
 (0)