Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python3 

2# -*- coding: utf-8; mode: python; -*- 

3# Copyright © 2021 Pradyumna Paranjape 

4# 

5# This file is part of xdgpspconf. 

6# 

7# xdgpspconf is free software: you can redistribute it and/or modify 

8# it under the terms of the GNU Lesser General Public License as published by 

9# the Free Software Foundation, either version 3 of the License, or 

10# (at your option) any later version. 

11# 

12# xdgpspconf is distributed in the hope that it will be useful, 

13# but WITHOUT ANY WARRANTY; without even the implied warranty of 

14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

15# GNU Lesser General Public License for more details. 

16# 

17# You should have received a copy of the GNU Lesser General Public License 

18# along with xdgpspconf. If not, see <https://www.gnu.org/licenses/>. 

19# 

20""" 

21Common filesystem discovery functions. 

22 

23""" 

24 

25import os 

26from pathlib import Path 

27from typing import Union 

28 

29 

30def fs_perm(path: Path, mode: Union[int, str] = 0, **permargs): 

31 """ 

32 Check read, write, execute permissions for effective id. 

33 

34 Args: 

35 path: check permissions of this location 

36 mode: permissions to check {[0-7],r,w,x,rw,wx,rx,rwx,} 

37 **permargs: 

38 

39 All are passed to :py:meth:`os.access` 

40 

41 Defaults: 

42 

43 - effective_ids: ``True`` 

44 - follow_symlinks ``True`` 

45 

46 Returns: 

47 ``True`` only if permissions are available or if perm is ``0`` 

48 """ 

49 if mode in ('0', 0, ''): 

50 return True 

51 mode_letter = {'x': 1, 'w': 2, 'r': 4} 

52 mode_code = (None, os.X_OK, os.W_OK, os.W_OK | os.X_OK, os.R_OK, 

53 os.R_OK | os.X_OK, os.R_OK | os.W_OK, 

54 os.R_OK | os.W_OK | os.X_OK) 

55 

56 # convert mode to octal 

57 oct_mode = 0 

58 try: 

59 if isinstance(mode, str): 

60 # new in 3.10, use match .. case 

61 # convert to int 

62 for p in list(mode): 

63 oct_mode += mode_letter[p] 

64 else: 

65 # permissions as integer 

66 oct_mode = mode % 8 

67 _mode = mode_code[oct_mode] 

68 except KeyError as err: 

69 raise KeyError(f'{err}\nmode: ([0-7]|r|w|x|rw|wx|rx|rwx|)') from None 

70 if _mode is None: 

71 # this should never happen 

72 # dummy check fallback 

73 return True 

74 while not path.exists(): 

75 path = path.parent 

76 for default in ('follow_symlinks', 'effective_ids'): 

77 permargs[default] = permargs.get(default, True) 

78 return os.access(path, _mode, **permargs) 

79 

80 

81def is_mount(path: Path): 

82 """ 

83 Check across platform if path is mountpoint (unix) or drive (win). 

84 

85 Args: 

86 path: path to be checked 

87 """ 

88 try: 

89 if path.is_mount(): 

90 return True 

91 return False 

92 except NotImplementedError: # pragma: no cover 

93 if path.resolve().drive + '\\' == str(path): 

94 return True 

95 return False