os.stat(myfile).st_mode 更好的 assertEqual()
Better assertEqual() for os.stat(myfile).st_mode
我有一个检查文件 st_mode 的代码:
self.assertEqual(16877, os.stat(my_directory).st_mode)
只有老派的 unix 专家才能流畅地解读整数值 16877
。
是否有更易读的方法来准确检查此值?
您可以使用定义的常量。它们可以在 stat
(docs) 中找到。他们是:
stat.S_IRUSR
所有者读取权限,
stat.S_IWUSR
所有者写权限,
stat.S_IXUSR
所有者执行权限,
stat.S_IRGRP
组读取权限,
stat.S_IWGRP
组写权限,
stat.S_IXGRP
组执行权限,
stat.S_IROTH
给其他人读权限,
stat.S_IWOTH
为他人写权限,
stat.S_IXOTH
给别人执行权限,
stat.S_IFDIR
目录。
它们可以使用按位或 |
组合。然后你的代码看起来像:
import stat
import os
permissions = (stat.S_IFDIR |
stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
self.assertEqual(permissions, os.stat(my_directory).st_mode)
Here 的一些关于 st_mode
的信息来自 stat
的手册,引用如下。
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 04000 set-user-ID bit
S_ISGID 02000 set-group-ID bit (see below)
S_ISVTX 01000 sticky bit (see below)
S_IRWXU 00700 owner has read, write, and execute permission
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 group has read, write, and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 others (not in group) have read, write, and
execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
这些都是八进制数。
oct(16877)
等同于 0o40755
。这意味着以下位处于活动状态:
40000
,或S_IFDIR
:目录
700
,表示所有者可以读、写、执行
50
,表示该组可读可执行,不可写。
5
,意思是world可以读和执行,但是不能写。
(755
是目录的模式。)
您可能可以做的一些事情:
Link 文档中的 stat
联机帮助页,或添加我粘贴的代码。然后,您可以使用
self.assertEqual(0o40755, os.stat(my_directory).st_mode)
相反,这意味着完全相同的东西,但更容易调试。
- 您可以使用
ctypes
模块自己实现位域。 python wiki 有更多信息。 (搜索 "Bit field"。)
您可以将 16877 或 0o40755(以及其他输出)作为常量变量的值,也许是全局变量。
DIR_755 = 0o40755
那么,你可以这样做:
self.assertEqual(DIR_755, os.stat(my_directory).st_mode)
检查模式是否正确。
你可以制作一个代码和值的字典:
st_mode_vals = {
"S_IFMT": 0170000, # Or instead, "filetype_bitmask"
"S_IFSOCK": 0140000, # Or instead, "socket"
...
"S_IXOTH": 0o1 # Or instead, "other_x"
}
然后您可以将它们定义为:
DIR_755 = st_mode_vals["directory"] +\
st_mode_vals["usr_rwx"] +\
st_mode_vals["grp_r"] + st_mode_vals["grp_x"] +\
st_mode_vals["oth_r"] + st_mode_vals["oth_x"]
self.assertEqual(DIR_755, os.stat(my_directory).st_mode)
我个人会使用#1(link 文档),如果某些代码经常重复使用,则使用#3。对于所有这些,也许您也可以添加注释以十进制表示值?
编辑:我没有看到我发布之前添加的答案。我不知道 stat
模块做了什么,所以我没有想到它。无论哪种方式,我想我仍然会使用#1 和#3。然而,他写的东西肯定会取代#4(字典)作为另一种选择,而且确实会好得多。
self.assertEqual(16877, os.stat(my_directory).st_mode)
Only old school unix experts are able to decipher the integer value 16877 fluently.
实际上,老派的 unix 专家可能会在同一条船上,因为这些东西是以八进制显示的。
我会:
- 切换到八进制以指定模式
- 添加文本表示和评论
像这样:
# 'my_directory' should be a directory with full permissions for user and
# read/execute permissions for group and other
# drwxr-xr-x
self.assertEqual(0o40755, os.stat(my_directory).st_mode)
如果我可以稍微扩展这个问题并将其理解为“是否有更易读的方法来检查文件模式?”,那么我会建议添加一个自定义断言。目标:
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。
我有一个检查文件 st_mode 的代码:
self.assertEqual(16877, os.stat(my_directory).st_mode)
只有老派的 unix 专家才能流畅地解读整数值 16877
。
是否有更易读的方法来准确检查此值?
您可以使用定义的常量。它们可以在 stat
(docs) 中找到。他们是:
stat.S_IRUSR
所有者读取权限,
stat.S_IWUSR
所有者写权限,
stat.S_IXUSR
所有者执行权限,
stat.S_IRGRP
组读取权限,
stat.S_IWGRP
组写权限,
stat.S_IXGRP
组执行权限,
stat.S_IROTH
给其他人读权限,
stat.S_IWOTH
为他人写权限,
stat.S_IXOTH
给别人执行权限,
stat.S_IFDIR
目录。
它们可以使用按位或 |
组合。然后你的代码看起来像:
import stat
import os
permissions = (stat.S_IFDIR |
stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
stat.S_IRGRP | stat.S_IXGRP |
stat.S_IROTH | stat.S_IXOTH)
self.assertEqual(permissions, os.stat(my_directory).st_mode)
Here 的一些关于 st_mode
的信息来自 stat
的手册,引用如下。
S_IFMT 0170000 bit mask for the file type bit field
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 04000 set-user-ID bit
S_ISGID 02000 set-group-ID bit (see below)
S_ISVTX 01000 sticky bit (see below)
S_IRWXU 00700 owner has read, write, and execute permission
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 group has read, write, and execute permission
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 others (not in group) have read, write, and
execute permission
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
这些都是八进制数。
oct(16877)
等同于 0o40755
。这意味着以下位处于活动状态:
40000
,或S_IFDIR
:目录700
,表示所有者可以读、写、执行50
,表示该组可读可执行,不可写。5
,意思是world可以读和执行,但是不能写。
(755
是目录的模式。)
您可能可以做的一些事情:
Link 文档中的
stat
联机帮助页,或添加我粘贴的代码。然后,您可以使用self.assertEqual(0o40755, os.stat(my_directory).st_mode)
相反,这意味着完全相同的东西,但更容易调试。
- 您可以使用
ctypes
模块自己实现位域。 python wiki 有更多信息。 (搜索 "Bit field"。) 您可以将 16877 或 0o40755(以及其他输出)作为常量变量的值,也许是全局变量。
DIR_755 = 0o40755
那么,你可以这样做:
self.assertEqual(DIR_755, os.stat(my_directory).st_mode)
检查模式是否正确。
你可以制作一个代码和值的字典:
st_mode_vals = { "S_IFMT": 0170000, # Or instead, "filetype_bitmask" "S_IFSOCK": 0140000, # Or instead, "socket" ... "S_IXOTH": 0o1 # Or instead, "other_x" }
然后您可以将它们定义为:
DIR_755 = st_mode_vals["directory"] +\ st_mode_vals["usr_rwx"] +\ st_mode_vals["grp_r"] + st_mode_vals["grp_x"] +\ st_mode_vals["oth_r"] + st_mode_vals["oth_x"] self.assertEqual(DIR_755, os.stat(my_directory).st_mode)
我个人会使用#1(link 文档),如果某些代码经常重复使用,则使用#3。对于所有这些,也许您也可以添加注释以十进制表示值?
编辑:我没有看到我发布之前添加的答案。我不知道 stat
模块做了什么,所以我没有想到它。无论哪种方式,我想我仍然会使用#1 和#3。然而,他写的东西肯定会取代#4(字典)作为另一种选择,而且确实会好得多。
self.assertEqual(16877, os.stat(my_directory).st_mode)
Only old school unix experts are able to decipher the integer value 16877 fluently.
实际上,老派的 unix 专家可能会在同一条船上,因为这些东西是以八进制显示的。
我会:
- 切换到八进制以指定模式
- 添加文本表示和评论
像这样:
# 'my_directory' should be a directory with full permissions for user and
# read/execute permissions for group and other
# drwxr-xr-x
self.assertEqual(0o40755, os.stat(my_directory).st_mode)
如果我可以稍微扩展这个问题并将其理解为“是否有更易读的方法来检查文件模式?”,那么我会建议添加一个自定义断言。目标:
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。