-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.py
76 lines (61 loc) · 2.24 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from configparser import ConfigParser
from fnmatch import fnmatch
from pathlib import Path
import re
import subprocess
import sys
def read_config():
dir = Path("@CMAKE_INSTALL_FULL_SYSCONFDIR@/automount")
paths = [ path for path in sorted(dir.glob("*.conf")) if path.is_file() ]
config = ConfigParser()
config.read(paths)
return config
def quote(s): return '"' + s + '"'
def unquote(s):
if s and (s[0] == '"' or s[0] == "'") and s[0] == s[-1]:
s = s[1:-1]
return s.replace('\\"', '"').replace("\\'", "'")
def split_quoted(s):
# ref: https://stackoverflow.com/a/51560564
pattern = re.compile(r'(?:[^"\s]*"(?:\\.|[^"])*"[^"\s]*)+|(?:[^\'\s]*\'(?:\\.|[^\'])*\'[^\'\s]*)+|[^\s]+')
return [ unquote(p) for p in re.findall(pattern, s) ]
def subst_vars(s, env):
pattern = re.compile(r'\$\{([^}]+)\}')
return re.sub(pattern, lambda match: env.get(match.group(1), ""), s)
def run(args, env={}):
if isinstance(args, str):
args = split_quoted(subst_vars(args, env))
print(f"Executing: {args}")
try:
proc = subprocess.run(args, capture_output=True)
if not proc.returncode: return proc.stdout.decode()
err = proc.stderr.decode()
except Exception as e:
err = str(e)
print(f"ERROR: {err}", file=sys.stderr)
return None
def udev_props(device):
out = run([ "/usr/bin/udevadm", "info", "-q", "env", device ])
env = {}
for line in out.splitlines():
key, value = line.split('=', 1)
env[key] = value
return env
def device_options(config, env):
options = {}
for section in config.sections():
match = True
for prop in split_quoted(section):
kv = prop.split("=", 1)
if not kv[0]: continue # ignore empty keys
if kv[0][0] == '!':
value = env.get(kv[0][1:])
match = value is None or not fnmatch(value, kv[1]) if len(kv) > 1 else False
else:
value = env.get(kv[0])
match = value is not None and fnmatch(value, kv[1]) if len(kv) > 1 else True
if not match: break
if match:
for option in config.options(section):
options[option] = config[section][option]
return options