Skip to content

Commit e1c910e

Browse files
gh-84649: Use statx() in TimedRotatingFileHandler if available
This allows to support rotation based on the file birth time on Linux.
1 parent c195a04 commit e1c910e

3 files changed

Lines changed: 25 additions & 16 deletions

File tree

Lib/logging/handlers.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,28 @@ def __init__(self, filename, when='h', interval=1, backupCount=0,
284284
if os.path.exists(filename):
285285
# Use the minimum of file creation and modification time as
286286
# the base of the rollover calculation
287-
stat_result = os.stat(filename)
288-
# Use st_birthtime whenever it is available or use st_ctime
289-
# instead otherwise
290-
try:
291-
creation_time = stat_result.st_birthtime
292-
except AttributeError:
293-
creation_time = stat_result.st_ctime
294-
t = int(min(creation_time, stat_result.st_mtime))
287+
creation_time = modification_time = None
288+
if hasattr(os, 'statx'):
289+
statx_result = os.statx(filename,
290+
os.STATX_BTIME|os.STATX_CTIME|os.STATX_MTIME)
291+
# Use stx_btime whenever it is available or use stx_ctime
292+
# instead otherwise
293+
creation_time = statx_result.stx_btime
294+
if creation_time is None:
295+
creation_time = statx_result.stx_ctime
296+
modification_time = statx_result.stx_mtime
297+
if creation_time is None or modification_time is None:
298+
stat_result = os.stat(filename)
299+
# Use st_birthtime whenever it is available or use st_ctime
300+
# instead otherwise
301+
if creation_time is None:
302+
try:
303+
creation_time = stat_result.st_birthtime
304+
except AttributeError:
305+
creation_time = stat_result.st_ctime
306+
if modification_time is None:
307+
modification_time = stat_result.st_mtime
308+
t = int(min(creation_time, modification_time))
295309
else:
296310
t = int(time.time())
297311
self.rolloverAt = self.computeRollover(t)

Lib/test/support/__init__.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"has_fork_support", "requires_fork",
4141
"has_subprocess_support", "requires_subprocess",
4242
"has_socket_support", "requires_working_socket",
43-
"has_st_birthtime",
4443
"has_remote_subprocess_debugging", "requires_remote_subprocess_debugging",
4544
"anticipate_failure", "load_package_tests", "detect_api_mismatch",
4645
"check__all__", "skip_if_buggy_ucrt_strfptime",
@@ -621,10 +620,6 @@ def skip_wasi_stack_overflow():
621620
or is_android
622621
)
623622

624-
# At the moment, st_birthtime attribute is only supported on Windows,
625-
# MacOS and FreeBSD.
626-
has_st_birthtime = sys.platform.startswith(("win", "freebsd", "darwin"))
627-
628623
def requires_fork():
629624
return unittest.skipUnless(has_fork_support, "requires working os.fork()")
630625

Lib/test/test_logging.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6615,9 +6615,9 @@ def test_rollover(self):
66156615
print(tf.read())
66166616
self.assertTrue(found, msg=msg)
66176617

6618-
@unittest.skipUnless(support.has_st_birthtime,
6619-
"st_birthtime not available or supported by Python on this OS")
6620-
@support.requires_resource('walltime')
6618+
@unittest.skipUnless(hasattr(os.stat_result, 'st_birthtime') or hasattr(os, 'statx'),
6619+
"st_birthtime and statx() not available or supported by Python on this OS")
6620+
# @support.requires_resource('walltime')
66216621
def test_rollover_based_on_st_birthtime_only(self):
66226622
def add_record(message: str) -> None:
66236623
fh = logging.handlers.TimedRotatingFileHandler(

0 commit comments

Comments
 (0)