Check if file is deletable

How to check in python if file is deletable without deleting it? After all I will delete it with:

try:
    os.remove(file_path)
except OSError as error:
    print(error)

So there is no problem with security hole between check and delete. I just have to inform user before press button that something is wrong.

Answer

Explanation

To check if file is deletable I have to check if file_path has write permission.

os.access(file_path, os.W_OK)

This is not enough. Deleting a file requires also write and execute permissions on the directory containing the file. So I have to check if directory containing the file has write and execute premissions.

os.access(file_dirname, os.W_OK | os.X_OK)

This is still not enough. File can be locked by other process, so I have to check that I can access the file.

try:
    file = open(file_path, 'w')
    file.close()
except OSError:
    print('File locked')

I can also check if file_path is a file.

os.path.isfile(file_path)

Solution

def is_file_deletable(file_path):
    ''' return True if file is deletable, False otherwise '''

    file_dirname = os.path.dirname(file_path)  # get the directory name of file_path

    if os.path.isfile(file_path):  # if file_path exists and is a file
        if os.access(file_path, os.W_OK):  # if file_path has write permission
            if os.access(file_dirname, os.W_OK | os.X_OK):  # if directory containing file_path has write and execute premisions
                try:  # if file_path can be opened for write
                    file = open(file_path, 'w')
                    file.close()
                    return True  # file_path is not locked
                except OSError:  # if file_path can't be opened for write
                    pass  # file_path is locked

    return False

Short version

def is_file_deletable(file_path):

    file_dirname = os.path.dirname(file_path)  # get the directory name of file_path

    if os.access(file_dirname, os.W_OK | os.X_OK):  # if folder containing file_path has write and execute permission
        try:  # if file_path can be opened for write
            file = open(file_path, 'w')
            file.close()
            return True  # file_path is a file and has write permission and is not locked
        except OSError:  # if file_path can't be opened for write
            pass  # file_path is not a file, or don't has write permission or is locked

    return False