Search code examples
pythonchmodreadabilitystat

Better assertEqual() for os.stat(myfile).st_mode


I have a code that checks the st_mode of a file:

self.assertEqual(16877, os.stat(my_directory).st_mode)

Only old school unix experts are able to decipher the integer value 16877 fluently.

Is there more readable way to check for exactly this value?


Solution

  • If I may extend the question a bit and understand it as “Is there more readable way to check file modes?”, then I'll suggest adding a custom assertion. The target:

    self.assertFileMode(my_directory, user="rwx", group="rx", others="rx")
    

    How to do it.

    Let's put that assertion in a 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))
    

    Using it

    Now, how about we test some file modes?

    # 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')
    

    Example output:

    AssertionError: user permissions: rw != rwx for /foo/bar
    

    Notes:

    • Only permissions given to the method are tested. To test that no permissions exist, pass an empty string.
    • Most of the complexity comes from generating a user-friendly message.
    • Permissions are sorted alphabetically in the error messages, so they are easier to eyeball-compare.
    • To keep it simple, I did not handle testing the sticky bit.