LIRC libraries
Linux Infrared Remote Control
Loading...
Searching...
No Matches
database.py
1''' Read-only configuration database. '''
2
7
8
34
35
37
38
39import glob
40import os
41import os.path
42import subprocess
43import sys
44
45try:
46 import yaml
47except ImportError:
48 _YAML_MSG = '''
49"Cannot import the yaml library. Please install the python3
50yaml package, on many distributions known as python3-PyYAML. It is also
51available as a pypi package at https://pypi.python.org/pypi/PyYAML.'''
52 print(_YAML_MSG)
53 sys.exit(1)
54
55import config
56
57
58def _here(path):
59 ''' Return path added to current dir for __file__. '''
60 return os.path.join(os.path.dirname(os.path.abspath(__file__)), path)
61
62
63def _load_kerneldrivers(configdir):
64 ''' Parse the kerneldrivers.yaml file, discard unavailable
65 drivers.
66 '''
67
68 with open(os.path.join(configdir, "kernel-drivers.yaml")) as f:
69 cf = yaml.load(f.read())
70 drivers = cf['drivers'].copy()
71 for driver in cf['drivers']:
72 if driver == 'default':
73 continue
74 with open('/dev/null', 'w') as f:
75 try:
76 subprocess.check_output([config.MODINFO, driver],
77 stderr=f)
78 except subprocess.CalledProcessError:
79 del drivers[driver]
80 return drivers
81
82
83class ItemLookupError(Exception):
84 """A lookup failed, either too namy or no matches found. """
85 pass
86
87
88class Config(object):
89 ''' The configuration selected, and it's sources. '''
90 # pylint: disable=too-many-instance-attributes
91
92 def __init__(self, cf=None):
93 self.device = None
94 self.driver = {}
95 self.config = {}
96 self.modinit = ""
97 self.modprobe = ""
98 self.lircd_conf = ""
99 self.lircmd_conf = ""
100 self.label = ""
101 if cf:
102 for key, value in cf.items():
103 setattr(self, key, value)
104
105 @property
106 def note(self):
107 ''' The possible note to display when selected. '''
108 if 'note' in self.config:
109 return self.config['note']
110 else:
111 return None
112
113
114class Database(object):
115 ''' Reflects the *.yaml files in the configs/ directory. '''
116
117 def __init__(self, path=None, yamlpath=None):
118
119 devel_path = _here('../../configs')
120 installed_path = os.path.join(config.DATADIR, 'lirc','configs')
121 if path and os.path.exists(path):
122 configdir = path
123 elif path:
124 raise FileNotFoundError(path)
125 elif os.path.exists(devel_path):
126 configdir = devel_path
127 elif os.path.exists(installed_path):
128 configdir = installed_path
129 else:
130 raise FileNotFoundError(devel_path + ':' + installed_path)
131 if not yamlpath:
132 yamlpath = configdir
133 db = {}
134 with open(os.path.join(yamlpath, "confs_by_driver.yaml")) as f:
135 cf = yaml.load(f.read())
136 db['lircd_by_driver'] = cf['lircd_by_driver'].copy()
137 db['lircmd_by_driver'] = cf['lircmd_by_driver'].copy()
138
139 db['kernel-drivers'] = _load_kerneldrivers(configdir)
140 db['drivers'] = db['kernel-drivers'].copy()
141 with open(os.path.join(yamlpath, "drivers.yaml")) as f:
142 cf = yaml.load(f.read())
143 db['drivers'].update(cf['drivers'].copy())
144 for key, d in db['drivers'].items():
145 d['id'] = key
146 hint = d['device_hint']
147 if not hint:
148 continue
149 hint = hint.strip()
150 if hint.startswith('"') and hint.endswith('"'):
151 hint = hint[1:-1]
152 hint = hint.replace(r'\"', "@$#!")
153 hint = hint.replace('"', '')
154 hint = hint.replace("@$#!", '"')
155 hint = hint.replace("\\\\", "\\")
156 d['device_hint'] = hint
157
158 configs = {}
159 for path in glob.glob(configdir + '/*.conf'):
160 with open(path) as f:
161 cf = yaml.load(f.read())
162 configs[cf['config']['id']] = cf['config']
163 db['configs'] = configs
164 self.db = db
165
166 @property
167 def kernel_drivers(self):
168 ''' The kernel-drivers dictionary, drivers.yaml + kernel-drivers.yaml.
169 '''
170 return self.db['kernel-drivers']
171
172 @property
173 def drivers(self):
174 ''' The drivers dictionary, drivers.yaml + kernel-drivers.yaml. '''
175 return self.db['drivers']
176
177 @property
178 def configs(self):
179 ''' Return dict of parsed config/*.conf files, keyd by id. '''
180 return self.db['configs']
181
182 def remotes_by_driver(self, driver):
183 ''' Return the list of remotes suggested for a given driver. '''
184 if isinstance(driver, dict):
185 driver = driver['id']
186 try:
187 return self.db['lircd_by_driver'][driver]
188 except KeyError:
189 return []
190
191 def lircmd_by_driver(self, driver):
192 ''' Return list of lircmd.conf file for given driver or None. '''
193 if isinstance(driver, dict):
194 driver = driver['id']
195 try:
196 return self.db['lircmd_by_driver'][driver]
197 except KeyError:
198 return []
199
200 def driver_by_remote(self, remote):
201 ''' Return the driver (possibly None) suggested for a remote. '''
202 for driver, files in self.db['lircd_by_driver'].items():
203 if remote in files:
204 return self.db['drivers'][driver]
205 return None
206
207 def find_config(self, key, value):
208 ''' Return item (a config) in configs where config[key] == value. '''
209 found = [c for c in self.db['configs'].values()
210 if key in c and c[key] == value]
211 if len(found) > 1:
212 raise ItemLookupError(
213 "find_config: Too many matches for %s, %s): " % (key, value)
214 + ', '.join([c['id'] for c in found]))
215 elif not found:
216 raise ItemLookupError(
217 "find_config: Nothing found for %s, %s): " % (key, value))
218 found = dict(found[0])
219 if 'device_hint' not in found:
220 try:
221 found['device_hint'] = \
222 self.db['drivers'][found['driver']]['device_hint']
223 except KeyError:
224 found['device_hint'] = \
225 self.db['kernel-drivers'][found['driver']]['device_hint']
226 return found
227
228
230
231# vim: set expandtab ts=4 sw=4: