ファイルのパーミッションを変更するコードを書く
Unix系ならばコマンド
chmod
を使ってファイルのパーミッションを変更する。
Pythonも
os.chmodでできるが、指定できるmodeはint型だけを許容し、
u+x
のように指定できない。
Pythonでも文字列によりパーミッションを変更したい…
できるだけUnix系の
chmod
の機能に近づけたい欲とコードをシンプルに保ちたい欲との葛藤を経て、コードを書く。
import os
def get_delta(mode, delim):
mode_shift = {'u': 6, 'g': 3, 'o': 0}
mode_delta = {'r': 0b100, 'w': 0b010, 'x': 0b001}
(owner, mode) = mode.split(delim, 1)
if len(owner) == 0: owner = 'ugo'
owner = owner.replace('a', 'ugo')
owner = ''.join(set(owner))
if len(mode) == 0: mode = 'rwx'
mode = ''.join(set(mode))
for o in owner:
if not o in mode_shift: raise ValueError
for m in mode:
if not m in mode_delta: raise ValueError
delta = 0b0
delta0 = 0b0
for m in mode: delta0 |= mode_delta[m]
for o, shift_bit in mode_shift.items():
if o in owner: delta |= delta0 << shift_bit
return delta
def get_mode(path, mask=0o777):
return os.stat(path).st_mode & mask
def set_mode(path, mode):
if type(mode) is str and mode[:2] in ('0o', '0x'): mode = int(mode[2:], 8)
if type(mode) is int: os.chmod(path, mode)
if type(mode) is str:
for mode in mode.split(','):
mode = mode.strip()
mask = 0o777
delta = 0o0
if '-' in mode: mask &= ~ get_delta(mode, '-')
elif '+' in mode:
delta = get_delta(mode, '+')
mask &= ~ delta
os.chmod(path, get_mode(path) & mask | delta)
# 試験
path = './sqlite.py'
for mode in (0o753, '0o753', '0x753', 'a+wr', 'u-wr', 'g+,o+r,u+w', 'ugo-,ug+x,g-x', 'a+,a-x'):
set_mode(path, mode)
print(oct(get_mode(path)))
2021/11/27 22:06