1 ''' Read-only configuration database. ''' 
   48         from yaml 
import CLoader 
as Loader, CDumper 
as Dumper
 
   50         from yaml 
import Loader, Dumper
 
   53 "Cannot import the yaml library. Please install the python3 
   54 yaml package, on many distributions known as python3-PyYAML. It is also 
   55 available as a pypi package at https://pypi.python.org/pypi/PyYAML.''' 
   63     ''' Return path added to current dir for __file__. ''' 
   64     return os.path.join(os.path.dirname(os.path.abspath(__file__)), path)
 
   67 def _load_kerneldrivers(configdir):
 
   68     ''' Parse the kerneldrivers.yaml file, discard unavailable 
   72     with open(os.path.join(configdir, 
"kernel-drivers.yaml")) 
as f:
 
   73         cf = yaml.load(f.read(), Loader = Loader)
 
   74     drivers = cf[
'drivers'].copy()
 
   75     for driver 
in cf[
'drivers']:
 
   76         if driver == 
'default':
 
   78         with open(
'/dev/null', 
'w') 
as f:
 
   80                 subprocess.check_output([config.MODINFO, driver],
 
   82             except subprocess.CalledProcessError:
 
   87 class ItemLookupError(Exception):
 
   88     """A lookup failed, either too namy or no matches found. """ 
   93     ''' The configuration selected, and it's sources. ''' 
   96     def __init__(self, cf=None):
 
  103         self.lircmd_conf = 
""      
  106             for key, value 
in cf.items():
 
  107                 setattr(self, key, value)
 
  111         ''' The possible note to display when selected. ''' 
  112         if 'note' in self.config:
 
  113             return self.config[
'note']
 
  118 class Database(object):
 
  119     ''' Reflects the *.yaml files in the configs/ directory. ''' 
  121     def __init__(self, path=None, yamlpath=None):
 
  123         devel_path = _here(
'../../configs')
 
  124         installed_path = os.path.join(config.DATADIR, 
'lirc',
'configs')
 
  125         if path 
and os.path.exists(path):
 
  128             raise FileNotFoundError(path)
 
  129         elif os.path.exists(devel_path):
 
  130             configdir = devel_path
 
  131         elif os.path.exists(installed_path):
 
  132             configdir = installed_path
 
  134             raise FileNotFoundError(devel_path + 
':' + installed_path)
 
  138         with open(os.path.join(yamlpath, 
"confs_by_driver.yaml")) 
as f:
 
  139             cf = yaml.load(f.read(), Loader = Loader)
 
  140         db[
'lircd_by_driver'] = cf[
'lircd_by_driver'].copy()
 
  141         db[
'lircmd_by_driver'] = cf[
'lircmd_by_driver'].copy()
 
  143         db[
'kernel-drivers'] = _load_kerneldrivers(configdir)
 
  144         db[
'drivers'] = db[
'kernel-drivers'].copy()
 
  145         with open(os.path.join(yamlpath, 
"drivers.yaml")) 
as f:
 
  146             cf = yaml.load(f.read(), Loader = Loader)
 
  147         db[
'drivers'].update(cf[
'drivers'].copy())
 
  148         for key, d 
in db[
'drivers'].items():
 
  150             hint = d[
'device_hint']
 
  154             if hint.startswith(
'"') 
and hint.endswith(
'"'):
 
  156                 hint = hint.replace(
r'\"', 
"@$#!")
 
  157                 hint = hint.replace(
'"', 
'')
 
  158                 hint = hint.replace(
"@$#!", 
'"')
 
  159                 hint = hint.replace(
"\\\\", 
"\\")
 
  160             d[
'device_hint'] = hint
 
  163         for path 
in glob.glob(configdir + 
'/*.conf'):
 
  164             with open(path) 
as f:
 
  165                 cf = yaml.load(f.read(), Loader = Loader)
 
  166             configs[cf[
'config'][
'id']] = cf[
'config']
 
  167         db[
'configs'] = configs
 
  171     def kernel_drivers(self):
 
  172         ''' The kernel-drivers dictionary, drivers.yaml + kernel-drivers.yaml. 
  174         return self.db[
'kernel-drivers']
 
  178         ''' The drivers dictionary, drivers.yaml + kernel-drivers.yaml. ''' 
  179         return self.db[
'drivers']
 
  183         ''' Return dict of parsed config/*.conf files, keyd by id. ''' 
  184         return self.db[
'configs']
 
  186     def remotes_by_driver(self, driver):
 
  187         ''' Return the list of remotes suggested for a given driver. ''' 
  188         if isinstance(driver, dict):
 
  189             driver = driver[
'id']
 
  191             return self.db[
'lircd_by_driver'][driver]
 
  195     def lircmd_by_driver(self, driver):
 
  196         ''' Return list of lircmd.conf file for given driver or None. ''' 
  197         if isinstance(driver, dict):
 
  198             driver = driver[
'id']
 
  200             return self.db[
'lircmd_by_driver'][driver]
 
  204     def driver_by_remote(self, remote):
 
  205         ''' Return the driver (possibly None) suggested for a remote. ''' 
  206         for driver, files 
in self.db[
'lircd_by_driver'].items():
 
  208                 return self.db[
'drivers'][driver]
 
  211     def find_config(self, key, value):
 
  212         ''' Return item (a config) in configs where config[key] == value. ''' 
  213         found = [c 
for c 
in self.db[
'configs'].values()
 
  214                  if key 
in c 
and c[key] == value]
 
  216             raise ItemLookupError(
 
  217                 "find_config: Too many matches for %s, %s): " % (key, value)
 
  218                 + 
', '.join([c[
'id'] 
for c 
in found]))
 
  220             raise ItemLookupError(
 
  221                 "find_config: Nothing  found for %s, %s): " % (key, value))
 
  222         found = dict(found[0])
 
  223         if 'device_hint' not in found:
 
  225                 found[
'device_hint'] = \
 
  226                     self.db[
'drivers'][found[
'driver']][
'device_hint']
 
  228                 found[
'device_hint'] = \
 
  229                     self.db[
'kernel-drivers'][found[
'driver']][
'device_hint']