Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c77d9f3

Browse files
committed
Issue #11016: Add C implementation of the stat module as _stat
1 parent 6ce8d17 commit c77d9f3

9 files changed

Lines changed: 679 additions & 23 deletions

File tree

Doc/library/stat.rst

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
os.lstat() and os.fstat().
77
.. sectionauthor:: Skip Montanaro <[email protected]>
88

9-
**Source code:** :source:`Lib/stat.py`
9+
**Source code:** :source:`Modules/_stat.c`
10+
:source:`Lib/stat.py`
1011

1112
--------------
1213

@@ -15,6 +16,9 @@ results of :func:`os.stat`, :func:`os.fstat` and :func:`os.lstat` (if they
1516
exist). For complete details about the :c:func:`stat`, :c:func:`fstat` and
1617
:c:func:`lstat` calls, consult the documentation for your system.
1718

19+
.. versionchanged:: 3.4
20+
The stat module is backed by a C implementation.
21+
1822
The :mod:`stat` module defines the following functions to test for specific file
1923
types:
2024

@@ -53,6 +57,24 @@ types:
5357

5458
Return non-zero if the mode is from a socket.
5559

60+
.. function:: S_ISDOOR(mode)
61+
62+
Return non-zero if the mode is from a door.
63+
64+
.. versionadded:: 3.4
65+
66+
.. function:: S_ISPORT(mode)
67+
68+
Return non-zero if the mode is from an event port.
69+
70+
.. versionadded:: 3.4
71+
72+
.. function:: S_ISWHT(mode)
73+
74+
Return non-zero if the mode is from a whiteout.
75+
76+
.. versionadded:: 3.4
77+
5678
Two additional functions are defined for more general manipulation of the file's
5779
mode:
5880

@@ -113,6 +135,10 @@ readable string:
113135

114136
.. versionadded:: 3.3
115137

138+
.. versionchanged:: 3.4
139+
The function supports :data:`S_IFDOOR`, :data:`S_IFPORT` and
140+
:data:`S_IFWHT`.
141+
116142

117143
All the variables below are simply symbolic indexes into the 10-tuple returned
118144
by :func:`os.stat`, :func:`os.fstat` or :func:`os.lstat`.
@@ -210,6 +236,29 @@ Use of the functions above is more portable than use of the first set of flags:
210236

211237
FIFO.
212238

239+
.. data:: S_IFDOOR
240+
241+
Door.
242+
243+
.. versionadded:: 3.4
244+
245+
.. data:: S_IFPORT
246+
247+
Event port.
248+
249+
.. versionadded:: 3.4
250+
251+
.. data:: S_IFWHT
252+
253+
Whiteout.
254+
255+
.. versionadded:: 3.4
256+
257+
.. note::
258+
259+
:data:`S_IFDOOR`, :data:`S_IFPORT` or :data:`S_IFWHT` are defined as
260+
0 when the platform does not have support for the file types.
261+
213262
The following flags can also be used in the *mode* argument of :func:`os.chmod`:
214263

215264
.. data:: S_ISUID

Doc/whatsnew/3.4.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ functools
182182

183183
New :func:`functools.singledispatch` decorator: see the :pep:`443`.
184184

185-
186185
smtplib
187186
-------
188187

@@ -213,6 +212,12 @@ wave
213212
The :meth:`~wave.getparams` method now returns a namedtuple rather than a
214213
plain tuple. (Contributed by Claudiu Popa in :issue:`17487`.)
215214

215+
stat
216+
---
217+
218+
The stat module is now backed by a C implementation in :mod:`_stat`. A C
219+
implementation is required as most of the values aren't standardized and
220+
platform-dependent. (Contributed by Christian Heimes in :issue:`11016`.)
216221

217222
Optimizations
218223
=============

Lib/stat.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,9 @@ def filemode(mode):
147147
else:
148148
perm.append("-")
149149
return "".join(perm)
150+
151+
# If available, use C implementation
152+
try:
153+
from _stat import *
154+
except ModuleNotFoundError:
155+
pass

Lib/test/test_stat.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import unittest
22
import os
33
from test.support import TESTFN, run_unittest, import_fresh_module
4-
import stat
4+
5+
c_stat = import_fresh_module('stat', fresh=['_stat'])
6+
py_stat = import_fresh_module('stat', blocked=['_stat'])
57

68
class TestFilemode(unittest.TestCase):
9+
statmod = None
10+
711
file_flags = {'SF_APPEND', 'SF_ARCHIVED', 'SF_IMMUTABLE', 'SF_NOUNLINK',
812
'SF_SNAPSHOT', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN',
913
'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE'}
@@ -60,17 +64,17 @@ def setUp(self):
6064

6165
def get_mode(self, fname=TESTFN):
6266
st_mode = os.lstat(fname).st_mode
63-
modestr = stat.filemode(st_mode)
67+
modestr = self.statmod.filemode(st_mode)
6468
return st_mode, modestr
6569

6670
def assertS_IS(self, name, mode):
6771
# test format, lstrip is for S_IFIFO
68-
fmt = getattr(stat, "S_IF" + name.lstrip("F"))
69-
self.assertEqual(stat.S_IFMT(mode), fmt)
72+
fmt = getattr(self.statmod, "S_IF" + name.lstrip("F"))
73+
self.assertEqual(self.statmod.S_IFMT(mode), fmt)
7074
# test that just one function returns true
7175
testname = "S_IS" + name
7276
for funcname in self.format_funcs:
73-
func = getattr(stat, funcname, None)
77+
func = getattr(self.statmod, funcname, None)
7478
if func is None:
7579
if funcname == testname:
7680
raise ValueError(funcname)
@@ -88,35 +92,35 @@ def test_mode(self):
8892
st_mode, modestr = self.get_mode()
8993
self.assertEqual(modestr, '-rwx------')
9094
self.assertS_IS("REG", st_mode)
91-
self.assertEqual(stat.S_IMODE(st_mode),
92-
stat.S_IRWXU)
95+
self.assertEqual(self.statmod.S_IMODE(st_mode),
96+
self.statmod.S_IRWXU)
9397

9498
os.chmod(TESTFN, 0o070)
9599
st_mode, modestr = self.get_mode()
96100
self.assertEqual(modestr, '----rwx---')
97101
self.assertS_IS("REG", st_mode)
98-
self.assertEqual(stat.S_IMODE(st_mode),
99-
stat.S_IRWXG)
102+
self.assertEqual(self.statmod.S_IMODE(st_mode),
103+
self.statmod.S_IRWXG)
100104

101105
os.chmod(TESTFN, 0o007)
102106
st_mode, modestr = self.get_mode()
103107
self.assertEqual(modestr, '-------rwx')
104108
self.assertS_IS("REG", st_mode)
105-
self.assertEqual(stat.S_IMODE(st_mode),
106-
stat.S_IRWXO)
109+
self.assertEqual(self.statmod.S_IMODE(st_mode),
110+
self.statmod.S_IRWXO)
107111

108112
os.chmod(TESTFN, 0o444)
109113
st_mode, modestr = self.get_mode()
110114
self.assertS_IS("REG", st_mode)
111115
self.assertEqual(modestr, '-r--r--r--')
112-
self.assertEqual(stat.S_IMODE(st_mode), 0o444)
116+
self.assertEqual(self.statmod.S_IMODE(st_mode), 0o444)
113117
else:
114118
os.chmod(TESTFN, 0o700)
115119
st_mode, modestr = self.get_mode()
116120
self.assertEqual(modestr[:3], '-rw')
117121
self.assertS_IS("REG", st_mode)
118-
self.assertEqual(stat.S_IFMT(st_mode),
119-
stat.S_IFREG)
122+
self.assertEqual(self.statmod.S_IFMT(st_mode),
123+
self.statmod.S_IFREG)
120124

121125
def test_directory(self):
122126
os.mkdir(TESTFN)
@@ -162,25 +166,38 @@ def test_devices(self):
162166

163167
def test_module_attributes(self):
164168
for key, value in self.stat_struct.items():
165-
modvalue = getattr(stat, key)
169+
modvalue = getattr(self.statmod, key)
166170
self.assertEqual(value, modvalue, key)
167171
for key, value in self.permission_bits.items():
168-
modvalue = getattr(stat, key)
172+
modvalue = getattr(self.statmod, key)
169173
self.assertEqual(value, modvalue, key)
170174
for key in self.file_flags:
171-
modvalue = getattr(stat, key)
175+
modvalue = getattr(self.statmod, key)
172176
self.assertIsInstance(modvalue, int)
173177
for key in self.formats:
174-
modvalue = getattr(stat, key)
178+
modvalue = getattr(self.statmod, key)
175179
self.assertIsInstance(modvalue, int)
176180
for key in self.format_funcs:
177-
func = getattr(stat, key)
181+
func = getattr(self.statmod, key)
178182
self.assertTrue(callable(func))
179183
self.assertEqual(func(0), 0)
180184

181185

186+
class TestFilemodeCStat(TestFilemode):
187+
statmod = c_stat
188+
189+
formats = TestFilemode.formats | {'S_IFDOOR', 'S_IFPORT', 'S_IFWHT'}
190+
format_funcss = TestFilemode.format_funcs | {'S_ISDOOR', 'S_ISPORT',
191+
'S_ISWHT'}
192+
193+
194+
class TestFilemodePyStat(TestFilemode):
195+
statmod = py_stat
196+
197+
182198
def test_main():
183-
run_unittest(TestFilemode)
199+
run_unittest(TestFilemodeCStat)
200+
run_unittest(TestFilemodePyStat)
184201

185202
if __name__ == '__main__':
186203
test_main()

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ Core and Builtins
123123
Library
124124
-------
125125

126+
- Issue #11016: Add C implementation of the stat module as _stat.
127+
126128
- Issue #18248: Fix libffi build on AIX.
127129

128130
- Issue #18259: Declare sethostname in socketmodule.c for AIX

Modules/Setup.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ _operator _operator.c # operator.add() and similar goodies
117117
_collections _collectionsmodule.c # Container types
118118
itertools itertoolsmodule.c # Functions creating iterators for efficient looping
119119
atexit atexitmodule.c # Register functions to be run at interpreter-shutdown
120+
_stat _stat.c # stat.h interface
120121

121122
# access to ISO C locale support
122123
_locale _localemodule.c # -lintl

0 commit comments

Comments
 (0)