如果我可以稍微扩展一下这个问题并将其理解为“是否有更易读的方法来检查文件模式?”,那么我会建议添加一个自定义断言。目标:
self.assertFileMode(my_directory, user="rwx", group="rx", others="rx")
怎么做。
让我们把这个断言放在一个 mixin 中:
import os
import stat
class FileAssertions(object):
FILE_PERMS = {
'user': {'r': stat.S_IRUSR, 'w': stat.S_IWUSR, 'x': stat.S_IXUSR, 's': stat.S_ISUID},
'group': {'r': stat.S_IRGRP, 'w': stat.S_IWGRP, 'x': stat.S_IXGRP, 's': stat.S_ISGID},
'others': {'r': stat.S_IROTH, 'w': stat.S_IWOTH, 'x': stat.S_IXOTH},
}
def assertFileMode(self, path, **kwargs):
mode = os.stat(path).st_mode
for key, perm_defs in self.FILE_PERMS.items():
expected = kwargs.pop(key, None)
if expected is not None:
actual_perms = mode & sum(perm_defs.values())
expected_perms = sum(perm_defs[flag] for flag in expected)
if actual_perms != expected_perms:
msg = '{key} permissions: {expected} != {actual} for {path}'.format(
key=key, path=path,
expected=''.join(sorted(expected)),
actual=''.join(sorted(flag for flag, value in perm_defs.items()
if value & mode != 0))
)
raise self.failureException(msg)
if kwargs:
raise TypeError('assertFileMode: unknown arguments %s' % ', '.join(kwargs))
使用它
现在,我们来测试一些文件模式如何?
# We use our mixin
class MyTestCase(FileAssertions, TestCase):
def test_some_paths(self):
# Test all permissions
self.assertFileMode('/foo/bar', user='rwx', group='rx', others='')
# Only test user permissions
self.assertFileMode('/foo/bar', user='rwx')
# We support the suid/sgid bits as well
self.assertFileMode('/foo/bar', user='rwxs', group='rxs', others='rx')
示例输出:
AssertionError: user permissions: rw != rwx for /foo/bar
注意事项:
- 仅测试授予该方法的权限。要测试不存在权限,请传递一个空字符串。
- 大部分复杂性来自生成用户友好的消息。
- 权限在错误消息中按字母顺序排序,因此更易于目视比较。
- 为简单起见,我没有处理 sticky bit 的测试。