Skip to content

Commit 55db458

Browse files
committed
gh-83714: Use "stx_" prefix for all os.statx_result members
1 parent 60df1d7 commit 55db458

File tree

4 files changed

+71
-64
lines changed

4 files changed

+71
-64
lines changed

Doc/library/os.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3412,7 +3412,7 @@ features:
34123412
Information about a file returned by :func:`os.statx`.
34133413

34143414
:class:`!statx_result` has all the attributes that :class:`~stat_result` has
3415-
on Linux, making it :term:`duck-typing` compatible, but
3415+
on Linux, but using ``stx_`` prefix instead of ``st_``.
34163416
:class:`!statx_result` is not a subclass of :class:`~stat_result` and cannot
34173417
be used as a tuple.
34183418

Lib/test/test_os/test_os.py

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,8 @@ def check_statx_attributes(self, filename):
750750
result = os.statx(filename, maximal_mask)
751751
basic_result = os.stat(filename)
752752

753-
time_attributes = ('st_atime', 'st_mtime', 'st_ctime', 'st_birthtime')
753+
time_attributes = ('stx_atime', 'stx_mtime', 'stx_ctime',
754+
'stx_birthtime')
754755
# gh-83714: st_birthtime can be None on tmpfs even if STATX_BTIME mask
755756
# is used
756757
time_attributes = [name for name in time_attributes
@@ -759,43 +760,44 @@ def check_statx_attributes(self, filename):
759760

760761
# Check that valid attributes match os.stat.
761762
requirements = (
762-
('st_mode', os.STATX_TYPE | os.STATX_MODE),
763-
('st_nlink', os.STATX_NLINK),
764-
('st_uid', os.STATX_UID),
765-
('st_gid', os.STATX_GID),
766-
('st_atime', os.STATX_ATIME),
767-
('st_atime_ns', os.STATX_ATIME),
768-
('st_mtime', os.STATX_MTIME),
769-
('st_mtime_ns', os.STATX_MTIME),
770-
('st_ctime', os.STATX_CTIME),
771-
('st_ctime_ns', os.STATX_CTIME),
772-
('st_ino', os.STATX_INO),
773-
('st_size', os.STATX_SIZE),
774-
('st_blocks', os.STATX_BLOCKS),
775-
('st_birthtime', os.STATX_BTIME),
776-
('st_birthtime_ns', os.STATX_BTIME),
763+
('stx_mode', os.STATX_TYPE | os.STATX_MODE),
764+
('stx_nlink', os.STATX_NLINK),
765+
('stx_uid', os.STATX_UID),
766+
('stx_gid', os.STATX_GID),
767+
('stx_atime', os.STATX_ATIME),
768+
('stx_atime_ns', os.STATX_ATIME),
769+
('stx_mtime', os.STATX_MTIME),
770+
('stx_mtime_ns', os.STATX_MTIME),
771+
('stx_ctime', os.STATX_CTIME),
772+
('stx_ctime_ns', os.STATX_CTIME),
773+
('stx_ino', os.STATX_INO),
774+
('stx_size', os.STATX_SIZE),
775+
('stx_blocks', os.STATX_BLOCKS),
776+
('stx_birthtime', os.STATX_BTIME),
777+
('stx_birthtime_ns', os.STATX_BTIME),
777778
# unconditionally valid members
778-
('st_blksize', 0),
779-
('st_rdev', 0),
780-
('st_dev', 0),
779+
('stx_blksize', 0),
780+
('stx_rdev', 0),
781+
('stx_dev', 0),
781782
)
782783
for name, bits in requirements:
783-
if result.stx_mask & bits == bits and hasattr(basic_result, name):
784+
st_name = "st_" + name[4:]
785+
if result.stx_mask & bits == bits and hasattr(basic_result, st_name):
784786
x = getattr(result, name)
785-
b = getattr(basic_result, name)
787+
b = getattr(basic_result, st_name)
786788
self.assertEqual(type(x), type(b))
787789
if isinstance(x, float):
788790
self.assertAlmostEqual(x, b, msg=name)
789791
else:
790792
self.assertEqual(x, b, msg=name)
791793

792-
self.assertEqual(result.stx_rdev_major, os.major(result.st_rdev))
793-
self.assertEqual(result.stx_rdev_minor, os.minor(result.st_rdev))
794-
self.assertEqual(result.stx_dev_major, os.major(result.st_dev))
795-
self.assertEqual(result.stx_dev_minor, os.minor(result.st_dev))
794+
self.assertEqual(result.stx_rdev_major, os.major(result.stx_rdev))
795+
self.assertEqual(result.stx_rdev_minor, os.minor(result.stx_rdev))
796+
self.assertEqual(result.stx_dev_major, os.major(result.stx_dev))
797+
self.assertEqual(result.stx_dev_minor, os.minor(result.stx_dev))
796798

797799
members = [name for name in dir(result)
798-
if name.startswith('st_') or name.startswith('stx_')]
800+
if name.startswith('stx_')]
799801
for name in members:
800802
try:
801803
setattr(result, name, 1)

Lib/test/test_os/test_posix.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,17 +1672,22 @@ def test_chown_dir_fd(self):
16721672
with self.prepare_file() as (dir_fd, name, fullname):
16731673
posix.chown(name, os.getuid(), os.getgid(), dir_fd=dir_fd)
16741674

1675-
def check_statlike_dir_fd(self, func):
1675+
def check_statlike_dir_fd(self, func, prefix):
16761676
with self.prepare() as (dir_fd, name, fullname):
16771677
with open(fullname, 'w') as outfile:
16781678
outfile.write("testline\n")
16791679
self.addCleanup(posix.unlink, fullname)
16801680

1681+
def get(result, attr):
1682+
return getattr(result, prefix + attr)
1683+
16811684
s1 = func(fullname)
16821685
s2 = func(name, dir_fd=dir_fd)
1683-
self.assertEqual((s1.st_dev, s1.st_ino), (s2.st_dev, s2.st_ino))
1686+
self.assertEqual((get(s1, "dev"), get(s1, "ino")),
1687+
(get(s2, "dev"), get(s2, "ino")))
16841688
s2 = func(fullname, dir_fd=None)
1685-
self.assertEqual((s1.st_dev, s1.st_ino), (s2.st_dev, s2.st_ino))
1689+
self.assertEqual((get(s1, "dev"), get(s1, "ino")),
1690+
(get(s2, "dev"), get(s2, "ino")))
16861691

16871692
self.assertRaisesRegex(TypeError, 'should be integer or None, not',
16881693
func, name, dir_fd=posix.getcwd())
@@ -1700,13 +1705,13 @@ def check_statlike_dir_fd(self, func):
17001705

17011706
@unittest.skipUnless(os.stat in os.supports_dir_fd, "test needs dir_fd support in os.stat()")
17021707
def test_stat_dir_fd(self):
1703-
self.check_statlike_dir_fd(posix.stat)
1708+
self.check_statlike_dir_fd(posix.stat, prefix="st_")
17041709

17051710
@unittest.skipUnless(hasattr(posix, 'statx'), "test needs os.statx()")
17061711
def test_statx_dir_fd(self):
17071712
def func(path, **kwargs):
17081713
return posix.statx(path, os.STATX_INO, **kwargs)
1709-
self.check_statlike_dir_fd(func)
1714+
self.check_statlike_dir_fd(func, prefix="stx_")
17101715

17111716
@unittest.skipUnless(os.utime in os.supports_dir_fd, "test needs dir_fd support in os.utime()")
17121717
def test_utime_dir_fd(self):

Modules/posixmodule.c

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3330,17 +3330,17 @@ typedef struct {
33303330

33313331
static PyMemberDef pystatx_result_members[] = {
33323332
MM(stx_mask, Py_T_UINT, mask, "member validity mask"),
3333-
MM(st_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
3333+
MM(stx_blksize, Py_T_UINT, blksize, "blocksize for filesystem I/O"),
33343334
MM(stx_attributes, Py_T_ULONGLONG, attributes, "Linux inode attribute bits"),
3335-
MM(st_mode, Py_T_USHORT, mode, "protection bits"),
3335+
MM(stx_mode, Py_T_USHORT, mode, "protection bits"),
33363336
MM(stx_attributes_mask, Py_T_ULONGLONG, attributes_mask,
33373337
"Mask of supported bits in stx_attributes"),
33383338
MM(stx_rdev_major, Py_T_UINT, rdev_major, "represented device major number"),
33393339
MM(stx_rdev_minor, Py_T_UINT, rdev_minor, "represented device minor number"),
3340-
MX(st_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
3340+
MX(stx_rdev, Py_T_ULONGLONG, rdev, "device type (if inode device)"),
33413341
MM(stx_dev_major, Py_T_UINT, dev_major, "containing device major number"),
33423342
MM(stx_dev_minor, Py_T_UINT, dev_minor, "containing device minor number"),
3343-
MX(st_dev, Py_T_ULONGLONG, dev, "device"),
3343+
MX(stx_dev, Py_T_ULONGLONG, dev, "device"),
33443344
{NULL},
33453345
};
33463346

@@ -3361,9 +3361,9 @@ static PyMemberDef pystatx_result_members[] = {
33613361
return PyLong_FromUnsignedLong(value); \
33623362
}
33633363

3364-
STATX_GET_UINT(st_uid, stx_uid, STATX_UID)
3365-
STATX_GET_UINT(st_gid, stx_gid, STATX_GID)
3366-
STATX_GET_UINT(st_nlink, stx_nlink, STATX_NLINK)
3364+
STATX_GET_UINT(stx_uid, stx_uid, STATX_UID)
3365+
STATX_GET_UINT(stx_gid, stx_gid, STATX_GID)
3366+
STATX_GET_UINT(stx_nlink, stx_nlink, STATX_NLINK)
33673367
#ifdef HAVE_STRUCT_STATX_STX_DIO_MEM_ALIGN
33683368
STATX_GET_UINT(stx_dio_mem_align, stx_dio_mem_align, STATX_DIOALIGN)
33693369
STATX_GET_UINT(stx_dio_offset_align, stx_dio_offset_align, STATX_DIOALIGN)
@@ -3398,9 +3398,9 @@ STATX_GET_UINT(stx_atomic_write_unit_max_opt, stx_atomic_write_unit_max_opt,
33983398
return PyLong_FromUnsignedLongLong(value); \
33993399
}
34003400

3401-
STATX_GET_ULONGLONG(st_blocks, stx_blocks, STATX_BLOCKS)
3402-
STATX_GET_ULONGLONG(st_ino, stx_ino, STATX_INO)
3403-
STATX_GET_ULONGLONG(st_size, stx_size, STATX_SIZE)
3401+
STATX_GET_ULONGLONG(stx_blocks, stx_blocks, STATX_BLOCKS)
3402+
STATX_GET_ULONGLONG(stx_ino, stx_ino, STATX_INO)
3403+
STATX_GET_ULONGLONG(stx_size, stx_size, STATX_SIZE)
34043404
#ifdef HAVE_STRUCT_STATX_STX_MNT_ID
34053405
STATX_GET_ULONGLONG(stx_mnt_id, stx_mnt_id, STATX_MNT_ID)
34063406
#endif
@@ -3421,10 +3421,10 @@ STATX_GET_ULONGLONG(stx_subvol, stx_subvol, STATX_SUBVOL)
34213421
return PyFloat_FromDouble(sec); \
34223422
}
34233423

3424-
STATX_GET_DOUBLE(st_atime, atime_sec, STATX_ATIME)
3425-
STATX_GET_DOUBLE(st_birthtime, btime_sec, STATX_BTIME)
3426-
STATX_GET_DOUBLE(st_ctime, ctime_sec, STATX_CTIME)
3427-
STATX_GET_DOUBLE(st_mtime, mtime_sec, STATX_MTIME)
3424+
STATX_GET_DOUBLE(stx_atime, atime_sec, STATX_ATIME)
3425+
STATX_GET_DOUBLE(stx_birthtime, btime_sec, STATX_BTIME)
3426+
STATX_GET_DOUBLE(stx_ctime, ctime_sec, STATX_CTIME)
3427+
STATX_GET_DOUBLE(stx_mtime, mtime_sec, STATX_MTIME)
34283428

34293429
#define STATX_GET_NSEC(ATTR, MEMBER, MASK) \
34303430
static PyObject* \
@@ -3440,29 +3440,29 @@ STATX_GET_DOUBLE(st_mtime, mtime_sec, STATX_MTIME)
34403440
return stat_nanosecond_timestamp(state, ts->tv_sec, ts->tv_nsec); \
34413441
}
34423442

3443-
STATX_GET_NSEC(st_atime_ns, stx_atime, STATX_ATIME)
3444-
STATX_GET_NSEC(st_birthtime_ns, stx_btime, STATX_BTIME)
3445-
STATX_GET_NSEC(st_ctime_ns, stx_ctime, STATX_CTIME)
3446-
STATX_GET_NSEC(st_mtime_ns, stx_mtime, STATX_MTIME)
3443+
STATX_GET_NSEC(stx_atime_ns, stx_atime, STATX_ATIME)
3444+
STATX_GET_NSEC(stx_birthtime_ns, stx_btime, STATX_BTIME)
3445+
STATX_GET_NSEC(stx_ctime_ns, stx_ctime, STATX_CTIME)
3446+
STATX_GET_NSEC(stx_mtime_ns, stx_mtime, STATX_MTIME)
34473447

34483448
#define G(attr, doc) \
34493449
{#attr, pystatx_result_get_##attr, NULL, PyDoc_STR(doc), NULL}
34503450

34513451
static PyGetSetDef pystatx_result_getset[] = {
3452-
G(st_nlink, "number of hard links"),
3453-
G(st_uid, "user ID of owner"),
3454-
G(st_gid, "group ID of owner"),
3455-
G(st_ino, "inode"),
3456-
G(st_size, "total size, in bytes"),
3457-
G(st_blocks, "number of blocks allocated"),
3458-
G(st_atime, "time of last access"),
3459-
G(st_atime_ns, "time of last access in nanoseconds"),
3460-
G(st_birthtime, "time of creation"),
3461-
G(st_birthtime_ns, "time of creation in nanoseconds"),
3462-
G(st_ctime, "time of last change"),
3463-
G(st_ctime_ns, "time of last change in nanoseconds"),
3464-
G(st_mtime, "time of last modification"),
3465-
G(st_mtime_ns, "time of last modification in nanoseconds"),
3452+
G(stx_nlink, "number of hard links"),
3453+
G(stx_uid, "user ID of owner"),
3454+
G(stx_gid, "group ID of owner"),
3455+
G(stx_ino, "inode"),
3456+
G(stx_size, "total size, in bytes"),
3457+
G(stx_blocks, "number of blocks allocated"),
3458+
G(stx_atime, "time of last access"),
3459+
G(stx_atime_ns, "time of last access in nanoseconds"),
3460+
G(stx_birthtime, "time of creation"),
3461+
G(stx_birthtime_ns, "time of creation in nanoseconds"),
3462+
G(stx_ctime, "time of last change"),
3463+
G(stx_ctime_ns, "time of last change in nanoseconds"),
3464+
G(stx_mtime, "time of last modification"),
3465+
G(stx_mtime_ns, "time of last modification in nanoseconds"),
34663466
#ifdef HAVE_STRUCT_STATX_STX_MNT_ID
34673467
G(stx_mnt_id, "mount ID"),
34683468
#endif

0 commit comments

Comments
 (0)