Skip to content

Commit 937373f

Browse files
lisroachfacebook-github-bot
authored andcommitted
Backports import_module audit PR.
Summary: Backport of upstream PR-138311 which adds sys.audit calls for import_module. python/cpython#138311 Reviewed By: itamaro Differential Revision: D83073937 fbshipit-source-id: 3831c0e8ac424142149f2a92a5d9e7dde49a6440
1 parent ef95d6c commit 937373f

File tree

8 files changed

+97
-28
lines changed

8 files changed

+97
-28
lines changed

Lib/importlib/_bootstrap.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,14 @@ def _sanity_check(name, package, level):
13031303

13041304
def _find_and_load_unlocked(name, import_):
13051305
path = None
1306+
sys.audit(
1307+
"import",
1308+
name,
1309+
path,
1310+
getattr(sys, "path", None),
1311+
getattr(sys, "meta_path", None),
1312+
getattr(sys, "path_hooks", None)
1313+
)
13061314
parent = name.rpartition('.')[0]
13071315
parent_spec = None
13081316
if parent:

Lib/test/audit-tests.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import contextlib
99
import os
1010
import sys
11-
11+
import unittest.mock
12+
from test.support import swap_item
1213

1314
class TestHook:
1415
"""Used in standard hook tests to collect any logged events.
@@ -543,6 +544,83 @@ def hook(event, args):
543544
sys.addaudithook(hook)
544545
_winapi.CreateNamedPipe(pipe_name, _winapi.PIPE_ACCESS_DUPLEX, 8, 2, 0, 0, 0, 0)
545546

547+
def test_import_module():
548+
import importlib
549+
550+
with TestHook() as hook:
551+
importlib.import_module("importlib") # already imported, won't get logged
552+
importlib.import_module("email") # standard library module
553+
importlib.import_module("pythoninfo") # random module
554+
importlib.import_module(".audit_test_data.submodule", "test") # relative import
555+
importlib.import_module("test.audit_test_data.submodule2") # absolute import
556+
importlib.import_module("_testcapi") # extension module
557+
558+
actual = [a for e, a in hook.seen if e == "import"]
559+
assertSequenceEqual(
560+
[
561+
("email", None, sys.path, sys.meta_path, sys.path_hooks),
562+
("pythoninfo", None, sys.path, sys.meta_path, sys.path_hooks),
563+
("test.audit_test_data.submodule", None, sys.path, sys.meta_path, sys.path_hooks),
564+
("test.audit_test_data", None, sys.path, sys.meta_path, sys.path_hooks),
565+
("test.audit_test_data.submodule2", None, sys.path, sys.meta_path, sys.path_hooks),
566+
("_testcapi", None, sys.path, sys.meta_path, sys.path_hooks),
567+
("_testcapi", unittest.mock.ANY, None, None, None)
568+
],
569+
actual,
570+
)
571+
572+
def test_builtin__import__():
573+
import importlib # noqa: F401
574+
575+
with TestHook() as hook:
576+
__import__("importlib")
577+
__import__("email")
578+
__import__("pythoninfo")
579+
__import__("audit_test_data.submodule", level=1, globals={"__package__": "test"})
580+
__import__("test.audit_test_data.submodule2")
581+
__import__("_testcapi")
582+
583+
actual = [a for e, a in hook.seen if e == "import"]
584+
assertSequenceEqual(
585+
[
586+
("email", None, sys.path, sys.meta_path, sys.path_hooks),
587+
("pythoninfo", None, sys.path, sys.meta_path, sys.path_hooks),
588+
("test.audit_test_data.submodule", None, sys.path, sys.meta_path, sys.path_hooks),
589+
("test.audit_test_data", None, sys.path, sys.meta_path, sys.path_hooks),
590+
("test.audit_test_data.submodule2", None, sys.path, sys.meta_path, sys.path_hooks),
591+
("_testcapi", None, sys.path, sys.meta_path, sys.path_hooks),
592+
("_testcapi", unittest.mock.ANY, None, None, None)
593+
],
594+
actual,
595+
)
596+
597+
def test_import_statement():
598+
import importlib # noqa: F401
599+
# Set __package__ so relative imports work
600+
with swap_item(globals(), "__package__", "test"):
601+
with TestHook() as hook:
602+
import importlib # noqa: F401
603+
import email # noqa: F401
604+
import pythoninfo # noqa: F401
605+
from .audit_test_data import submodule # noqa: F401
606+
import test.audit_test_data.submodule2 # noqa: F401
607+
import _testcapi # noqa: F401
608+
609+
actual = [a for e, a in hook.seen if e == "import"]
610+
# Import statement ordering is different because the package is
611+
# loaded first and then the submodule
612+
assertSequenceEqual(
613+
[
614+
("email", None, sys.path, sys.meta_path, sys.path_hooks),
615+
("pythoninfo", None, sys.path, sys.meta_path, sys.path_hooks),
616+
("test.audit_test_data", None, sys.path, sys.meta_path, sys.path_hooks),
617+
("test.audit_test_data.submodule", None, sys.path, sys.meta_path, sys.path_hooks),
618+
("test.audit_test_data.submodule2", None, sys.path, sys.meta_path, sys.path_hooks),
619+
("_testcapi", None, sys.path, sys.meta_path, sys.path_hooks),
620+
("_testcapi", unittest.mock.ANY, None, None, None)
621+
],
622+
actual,
623+
)
546624

547625
if __name__ == "__main__":
548626
from test.support import suppress_msvcrt_asserts

Lib/test/audit_test_data/__init__.py

Whitespace-only changes.

Lib/test/audit_test_data/submodule.py

Whitespace-only changes.

Lib/test/audit_test_data/submodule2.py

Whitespace-only changes.

Lib/test/test_audit.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,5 +286,14 @@ def test_winapi_createnamedpipe(self):
286286

287287
self.assertEqual(actual, expected)
288288

289+
def test_import_module(self):
290+
self.do_test("test_import_module")
291+
292+
def test_builtin__import__(self):
293+
self.do_test("test_builtin__import__")
294+
295+
def test_import_statement(self):
296+
self.do_test("test_import_statement")
297+
289298
if __name__ == "__main__":
290299
unittest.main()

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2132,6 +2132,7 @@ TESTSUBDIRS= idlelib/idle_test \
21322132
test \
21332133
test/test_ast \
21342134
test/audiodata \
2135+
test/audit_test_data \
21352136
test/certdata \
21362137
test/certdata/capath \
21372138
test/cjkencodings \

Python/import.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,33 +2771,6 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
27712771

27722772
_PyTime_t t1 = 0, accumulated_copy = accumulated;
27732773

2774-
PyObject *sys_path, *sys_meta_path, *sys_path_hooks;
2775-
if (_PySys_GetOptionalAttrString("path", &sys_path) < 0) {
2776-
return NULL;
2777-
}
2778-
if (_PySys_GetOptionalAttrString("meta_path", &sys_meta_path) < 0) {
2779-
Py_XDECREF(sys_path);
2780-
return NULL;
2781-
}
2782-
if (_PySys_GetOptionalAttrString("path_hooks", &sys_path_hooks) < 0) {
2783-
Py_XDECREF(sys_meta_path);
2784-
Py_XDECREF(sys_path);
2785-
return NULL;
2786-
}
2787-
if (_PySys_Audit(tstate, "import", "OOOOO",
2788-
abs_name, Py_None, sys_path ? sys_path : Py_None,
2789-
sys_meta_path ? sys_meta_path : Py_None,
2790-
sys_path_hooks ? sys_path_hooks : Py_None) < 0) {
2791-
Py_XDECREF(sys_path_hooks);
2792-
Py_XDECREF(sys_meta_path);
2793-
Py_XDECREF(sys_path);
2794-
return NULL;
2795-
}
2796-
Py_XDECREF(sys_path_hooks);
2797-
Py_XDECREF(sys_meta_path);
2798-
Py_XDECREF(sys_path);
2799-
2800-
28012774
/* XOptions is initialized after first some imports.
28022775
* So we can't have negative cache before completed initialization.
28032776
* Anyway, importlib._find_and_load is much slower than

0 commit comments

Comments
 (0)