Skip to content

Commit

Permalink
Merge pull request #4627 from mwichmann/maint/st_mode
Browse files Browse the repository at this point in the history
Modernize stat usage
  • Loading branch information
bdbaddog authored Dec 16, 2024
2 parents 393792c + f906d01 commit 0c21de9
Show file tree
Hide file tree
Showing 29 changed files with 317 additions and 306 deletions.
2 changes: 2 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
Only object-like macros are replaced (not function-like), and
only on a whole-word basis; recursion is limited to five levels
and does not error out if that limit is reached (issue #4523).
- Minor modernization: make use of stat object's st_mode, st_mtime
and other attributes rather than indexing into stat return.
- The update-release-info test is adapted to accept changed help output
introduced in Python 3.12.8/3.13.1.

Expand Down
4 changes: 4 additions & 0 deletions RELEASE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ FIXES
only on a whole-word basis; recursion is limited to five levels
and does not error out if that limit is reached (issue #4523).

- Minor modernization: make use of stat object's st_mode, st_mtime
and other attributes rather than indexing into stat return.


IMPROVEMENTS
------------

Expand Down
2 changes: 1 addition & 1 deletion SCons/CacheDir.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def CacheRetrieveFunc(target, source, env) -> int:
except OSError:
pass
st = fs.stat(cachefile)
fs.chmod(t.get_internal_path(), stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
fs.chmod(t.get_internal_path(), stat.S_IMODE(st.st_mode) | stat.S_IWRITE)
return 0

def CacheRetrieveString(target, source, env) -> str:
Expand Down
2 changes: 2 additions & 0 deletions SCons/Node/FS.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,8 @@ def getmtime(self):
st = self.stat()

if st:
# TODO: switch to st.st_mtime, however this changes granularity
# (ST_MTIME is an int for backwards compat, st_mtime is float)
return st[stat.ST_MTIME]
else:
return None
Expand Down
2 changes: 2 additions & 0 deletions SCons/Node/FSTests.py
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,7 @@ def test_update(self) -> None:

ni.update(fff)

# TODO: flip this to st.st_mtime when Node/FS.py does
mtime = st[stat.ST_MTIME]
assert ni.timestamp == mtime, (ni.timestamp, mtime)
size = st.st_size
Expand All @@ -786,6 +787,7 @@ def test_update(self) -> None:

st = os.stat('fff')

# TODO: flip this to st.st_mtime when Node/FS.py does
mtime = st[stat.ST_MTIME]
assert ni.timestamp != mtime, (ni.timestamp, mtime)
size = st.st_size
Expand Down
4 changes: 2 additions & 2 deletions SCons/Tool/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def copyFunc(dest, source, env) -> int:
else:
copy2(source, dest)
st = os.stat(source)
os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
os.chmod(dest, stat.S_IMODE(st.st_mode) | stat.S_IWRITE)

return 0

Expand Down Expand Up @@ -204,7 +204,7 @@ def copyFuncVersionedLib(dest, source, env) -> int:
pass
copy2(source, dest)
st = os.stat(source)
os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
os.chmod(dest, stat.S_IMODE(st.st_mode) | stat.S_IWRITE)
installShlibLinks(dest, source, env)

return 0
Expand Down
2 changes: 1 addition & 1 deletion site_scons/Utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def whereis(filename):
st = os.stat(f_ext)
except:
continue
if stat.S_IMODE(st[stat.ST_MODE]) & 0o111:
if stat.S_IMODE(st.st_mode) & stat.S_IXUSR:
return f_ext
return None

Expand Down
2 changes: 1 addition & 1 deletion test/Actions/append.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def after(env, target, source):

test.run(arguments='.')
test.must_match('before.txt', 'Bar\n')
os.chmod(after_exe, os.stat(after_exe)[stat.ST_MODE] | stat.S_IXUSR)
os.chmod(after_exe, os.stat(after_exe).st_mode | stat.S_IXUSR)
test.run(program=after_exe, stdout="Foo\n")
test.pass_test()

Expand Down
4 changes: 2 additions & 2 deletions test/Actions/pre-post.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def before(env, target, source):
a=str(target[0])
with open(a, "wb") as f:
f.write(b"Foo\\n")
os.chmod(a, os.stat(a)[stat.ST_MODE] | stat.S_IXUSR)
os.chmod(a, os.stat(a).st_mode | stat.S_IXUSR)
with open("before.txt", "ab") as f:
f.write((os.path.splitext(str(target[0]))[0] + "\\n").encode())
Expand All @@ -59,7 +59,7 @@ def after(env, target, source):
a = "after_" + t
with open(t, "rb") as fin, open(a, "wb") as fout:
fout.write(fin.read())
os.chmod(a, os.stat(a)[stat.ST_MODE] | stat.S_IXUSR)
os.chmod(a, os.stat(a).st_mode | stat.S_IXUSR)
foo = env.Program(source='foo.c', target='foo')
AddPreAction(foo, before)
Expand Down
77 changes: 39 additions & 38 deletions test/Chmod.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def cat(env, source, target):
f.write(infp.read())
Cat = Action(cat)
DefaultEnvironment(tools=[]) # test speedup
env = Environment()
env.Command(
'bar.out',
Expand Down Expand Up @@ -154,92 +155,92 @@ def cat(env, source, target):
""")
test.run(options = '-n', arguments = '.', stdout = expect)

s = stat.S_IMODE(os.stat(test.workpath('f1'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f1')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('f1-File'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f1-File')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('d2'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d2')).st_mode)
test.fail_test(s != 0o555)
s = stat.S_IMODE(os.stat(test.workpath('d2-Dir'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d2-Dir')).st_mode)
test.fail_test(s != 0o555)
test.must_not_exist('bar.out')
s = stat.S_IMODE(os.stat(test.workpath('f3'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f3')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('d4'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d4')).st_mode)
test.fail_test(s != 0o555)
s = stat.S_IMODE(os.stat(test.workpath('f5'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f5')).st_mode)
test.fail_test(s != 0o444)
test.must_not_exist('f6.out')
test.must_not_exist('f7.out')
s = stat.S_IMODE(os.stat(test.workpath('Chmod-f7.in'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('Chmod-f7.in')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('f7.out-Chmod'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f7.out-Chmod')).st_mode)
test.fail_test(s != 0o444)
test.must_not_exist('f8.out')
s = stat.S_IMODE(os.stat(test.workpath('f9'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f9')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('f10'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f10')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('d11'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d11')).st_mode)
test.fail_test(s != 0o555)
s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d12')).st_mode)
test.fail_test(s != 0o555)
s = stat.S_IMODE(os.stat(test.workpath('f13'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f13')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('f14'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f14')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('f15'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f15')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('d16'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d16')).st_mode)
test.fail_test(s != 0o555)
s = stat.S_IMODE(os.stat(test.workpath('d17'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d17')).st_mode)
test.fail_test(s != 0o555)
s = stat.S_IMODE(os.stat(test.workpath('d18'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d18')).st_mode)
test.fail_test(s != 0o555)

test.run()

s = stat.S_IMODE(os.stat(test.workpath('f1'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f1')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('f1-File'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f1-File')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('d2'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d2')).st_mode)
test.fail_test(s != 0o777)
s = stat.S_IMODE(os.stat(test.workpath('d2-Dir'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d2-Dir')).st_mode)
test.fail_test(s != 0o777)
test.must_match('bar.out', "bar.in\n")
s = stat.S_IMODE(os.stat(test.workpath('f3'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f3')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('d4'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d4')).st_mode)
test.fail_test(s != 0o777)
s = stat.S_IMODE(os.stat(test.workpath('f5'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f5')).st_mode)
test.fail_test(s != 0o666)
test.must_match('f6.out', "f6.in\n")
test.must_match('f7.out', "f7.in\n")
s = stat.S_IMODE(os.stat(test.workpath('Chmod-f7.in'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('Chmod-f7.in')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('f7.out-Chmod'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f7.out-Chmod')).st_mode)
test.fail_test(s != 0o666)
test.must_match('f8.out', "f8.in\n")
s = stat.S_IMODE(os.stat(test.workpath('f9'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f9')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('f10'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f10')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('d11'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d11')).st_mode)
test.fail_test(s != 0o777)
s = stat.S_IMODE(os.stat(test.workpath('d12'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d12')).st_mode)
test.fail_test(s != 0o777)
s = stat.S_IMODE(os.stat(test.workpath('f13'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f13')).st_mode)
test.fail_test(s != 0o444)
s = stat.S_IMODE(os.stat(test.workpath('f14'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f14')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('f15'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('f15')).st_mode)
test.fail_test(s != 0o666)
s = stat.S_IMODE(os.stat(test.workpath('d16'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d16')).st_mode)
test.fail_test(s != 0o777)
s = stat.S_IMODE(os.stat(test.workpath('d17'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d17')).st_mode)
test.fail_test(s != 0o777)
s = stat.S_IMODE(os.stat(test.workpath('d18'))[stat.ST_MODE])
s = stat.S_IMODE(os.stat(test.workpath('d18')).st_mode)
test.fail_test(s != 0o777)

test.pass_test()
Expand Down
2 changes: 1 addition & 1 deletion test/Decider/MD5-timestamp-Repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
test.sleep() # delay for timestamps
test.write(['Repository','content1.in'], "content1.in 2\n")
test.touch(['Repository','content2.in'])
time_content = os.stat(os.path.join(repository,'content3.in'))[stat.ST_MTIME]
time_content = os.stat(os.path.join(repository,'content3.in')).st_mtime
test.write(['Repository','content3.in'], "content3.in 2\n")
test.touch(['Repository','content3.in'], time_content)

Expand Down
2 changes: 1 addition & 1 deletion test/Decider/MD5-timestamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
test.write('content1.in', "content1.in 2\n")
test.touch('content2.in')

time_content = os.stat('content3.in')[stat.ST_MTIME]
time_content = os.stat('content3.in').st_mtime
test.write('content3.in', "content3.in 2\n")
test.touch('content3.in', time_content)

Expand Down
4 changes: 2 additions & 2 deletions test/Decider/timestamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
test.run(arguments = '.')
test.up_to_date(arguments = '.')

time_match = os.stat('match2.out')[stat.ST_MTIME]
time_newer = os.stat('newer2.out')[stat.ST_MTIME]
time_match = os.stat('match2.out').st_mtime
time_newer = os.stat('newer2.out').st_mtime

# Now make all the source files newer than (different timestamps from)
# the last time the targets were built, and touch the target files
Expand Down
6 changes: 3 additions & 3 deletions test/Removed/BuildDir/Old/BuildDir.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,16 @@ def filter_tempnam(err):
def equal_stats(x,y):
x = os.stat(x)
y = os.stat(y)
return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and
x[stat.ST_MTIME] == y[stat.ST_MTIME])
return (stat.S_IMODE(x.st_mode) == stat.S_IMODE(y.st_mode) and
x.st_mtime == y.st_mtime)

# Make sure we did duplicate the source files in build/var2,
# and that their stats are the same:
test.must_exist(['work1', 'build', 'var2', 'f1.c'])
test.must_exist(['work1', 'build', 'var2', 'f2.in'])
test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f1.c'), test.workpath('work1', 'src', 'f1.c')))
test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f2.in'), test.workpath('work1', 'src', 'f2.in')))

# Make sure we didn't duplicate the source files in build/var3.
test.must_not_exist(['work1', 'build', 'var3', 'f1.c'])
test.must_not_exist(['work1', 'build', 'var3', 'f2.in'])
Expand Down
22 changes: 11 additions & 11 deletions test/Removed/BuildDir/Old/SConscript-build_dir.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
# __COPYRIGHT__
# MIT License
#
# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
Expand All @@ -20,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"

"""
Verify that specifying a build_dir argument to SConscript still works.
Expand Down Expand Up @@ -108,7 +107,7 @@ def cat(env, source, target):
# VariantDir('build/var9', '.')
# SConscript('build/var9/src/SConscript')
SConscript('src/SConscript', build_dir='build/var9', src_dir='.')
""")
""")

test.subdir(['test', 'src'], ['test', 'alt'])

Expand Down Expand Up @@ -152,8 +151,8 @@ def cat(env, source, target):
def equal_stats(x,y):
x = os.stat(x)
y = os.stat(y)
return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and
x[stat.ST_MTIME] == y[stat.ST_MTIME])
return (stat.S_IMODE(x.st_mode) == stat.S_IMODE(y.st_mode) and
x.st_mtime == y.st_mtime)

# Make sure we did duplicate the source files in build/var1,
# and that their stats are the same:
Expand All @@ -168,12 +167,12 @@ def equal_stats(x,y):
test.must_exist(test.workpath('test', 'build', 'var2', file))
test.fail_test(not equal_stats(test.workpath('test', 'build', 'var2', file),
test.workpath('test', 'src', file)))

# Make sure we didn't duplicate the source files in build/var3.
test.must_not_exist(test.workpath('test', 'build', 'var3', 'aaa.in'))
test.must_not_exist(test.workpath('test', 'build', 'var3', 'bbb.in'))
test.must_not_exist(test.workpath('test', 'build', 'var3', 'ccc.in'))

#XXX We can't support var4 and var5 yet, because our VariantDir linkage
#XXX is to an entire source directory. We haven't yet generalized our
#XXX infrastructure to be able to take the SConscript file from one source
Expand All @@ -200,12 +199,12 @@ def equal_stats(x,y):
test.must_exist(test.workpath('build', 'var6', file))
test.fail_test(not equal_stats(test.workpath('build', 'var6', file),
test.workpath('test', 'src', file)))

# Make sure we didn't duplicate the source files in build/var7.
test.must_not_exist(test.workpath('build', 'var7', 'aaa.in'))
test.must_not_exist(test.workpath('build', 'var7', 'bbb.in'))
test.must_not_exist(test.workpath('build', 'var7', 'ccc.in'))

# Make sure we didn't duplicate the source files in build/var8.
test.must_not_exist(test.workpath('build', 'var8', 'aaa.in'))
test.must_not_exist(test.workpath('build', 'var8', 'bbb.in'))
Expand All @@ -219,6 +218,7 @@ def equal_stats(x,y):
""")

test.write(['test2', 'SConscript'], """\
DefaultEnvironment(tools=[]) # test speedup
env = Environment()
foo_obj = env.Object('foo.c')
env.Program('foo', [foo_obj, 'bar.c'])
Expand Down
Loading

0 comments on commit 0c21de9

Please sign in to comment.