From 31b61d19abcc63aa28625a31ed75411948fc1e7e Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 23 Aug 2023 11:00:22 +0200 Subject: [PATCH] gh-108294: Add time.sleep audit event (GH-108298) --- Doc/library/time.rst | 5 +++++ Lib/test/audit-tests.py | 15 +++++++++++++++ Lib/test/test_audit.py | 15 +++++++++++++++ ...2023-08-22-16-18-49.gh-issue-108294.KEeUcM.rst | 1 + Modules/timemodule.c | 2 ++ 5 files changed, 38 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2023-08-22-16-18-49.gh-issue-108294.KEeUcM.rst diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 9f23a6fc7d5..6ffe4ac4284 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -379,6 +379,8 @@ Functions * Or use ``nanosleep()`` if available (resolution: 1 nanosecond); * Or use ``select()`` (resolution: 1 microsecond). + .. audit-event:: time.sleep secs + .. versionchanged:: 3.11 On Unix, the ``clock_nanosleep()`` and ``nanosleep()`` functions are now used if available. On Windows, a waitable timer is now used. @@ -389,6 +391,9 @@ Functions :pep:`475` for the rationale). + .. versionchanged:: 3.13 + Raises an auditing event. + .. index:: single: % (percent); datetime format diff --git a/Lib/test/audit-tests.py b/Lib/test/audit-tests.py index 9504829e96f..cc614eab908 100644 --- a/Lib/test/audit-tests.py +++ b/Lib/test/audit-tests.py @@ -514,6 +514,21 @@ def test_not_in_gc(): assert hook not in o +def test_time(): + import time + + def hook(event, args): + if event.startswith("time."): + print(event, *args) + sys.addaudithook(hook) + + time.sleep(0) + time.sleep(0.0625) # 1/16, a small exact float + try: + time.sleep(-1) + except ValueError: + pass + def test_sys_monitoring_register_callback(): import sys diff --git a/Lib/test/test_audit.py b/Lib/test/test_audit.py index b12ffa5d872..3a15835917c 100644 --- a/Lib/test/test_audit.py +++ b/Lib/test/test_audit.py @@ -256,6 +256,21 @@ class AuditTest(unittest.TestCase): if returncode: self.fail(stderr) + def test_time(self): + returncode, events, stderr = self.run_python("test_time") + if returncode: + self.fail(stderr) + + if support.verbose: + print(*events, sep='\n') + + actual = [(ev[0], ev[2]) for ev in events] + expected = [("time.sleep", "0"), + ("time.sleep", "0.0625"), + ("time.sleep", "-1")] + + self.assertEqual(actual, expected) + def test_sys_monitoring_register_callback(self): returncode, events, stderr = self.run_python("test_sys_monitoring_register_callback") diff --git a/Misc/NEWS.d/next/Library/2023-08-22-16-18-49.gh-issue-108294.KEeUcM.rst b/Misc/NEWS.d/next/Library/2023-08-22-16-18-49.gh-issue-108294.KEeUcM.rst new file mode 100644 index 00000000000..de2a3a8a8ad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-08-22-16-18-49.gh-issue-108294.KEeUcM.rst @@ -0,0 +1 @@ +:func:`time.sleep` now raises an auditing event. diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 912710219bd..68948b6be1a 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -414,6 +414,8 @@ Return the clk_id of a thread's CPU time clock."); static PyObject * time_sleep(PyObject *self, PyObject *timeout_obj) { + PySys_Audit("time.sleep", "O", timeout_obj); + _PyTime_t timeout; if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_TIMEOUT)) return NULL;