mirror of
https://github.com/sezanzeb/input-remapper
synced 2024-11-20 03:25:43 +00:00
tests for create preset, config lib not needed
This commit is contained in:
parent
02efe37389
commit
9ac1fefeb1
@ -100,9 +100,9 @@ class Window:
|
|||||||
# find an select the newest preset based on file modification dates
|
# find an select the newest preset based on file modification dates
|
||||||
device, preset = find_newest_preset()
|
device, preset = find_newest_preset()
|
||||||
if device is not None:
|
if device is not None:
|
||||||
self.on_select_device(device)
|
self.get('device_selection').set_active_id(device)
|
||||||
if preset is not None:
|
if preset is not None:
|
||||||
self.on_select_preset(preset)
|
self.get('device_selection').set_active_id(preset)
|
||||||
|
|
||||||
def get(self, name):
|
def get(self, name):
|
||||||
"""Get a widget from the window"""
|
"""Get a widget from the window"""
|
||||||
@ -117,7 +117,6 @@ class Window:
|
|||||||
devices = find_devices()
|
devices = find_devices()
|
||||||
device_selection = self.get('device_selection')
|
device_selection = self.get('device_selection')
|
||||||
for device in devices:
|
for device in devices:
|
||||||
ids = devices[device]
|
|
||||||
device_selection.append(device, device)
|
device_selection.append(device, device)
|
||||||
|
|
||||||
def populate_presets(self):
|
def populate_presets(self):
|
||||||
@ -130,10 +129,11 @@ class Window:
|
|||||||
# and select the newest one (on the top)
|
# and select the newest one (on the top)
|
||||||
preset_selection.set_active(0)
|
preset_selection.set_active(0)
|
||||||
|
|
||||||
def on_select_device(self, device):
|
def on_select_device(self, dropdown):
|
||||||
"""List all presets, create one if none exist yet."""
|
"""List all presets, create one if none exist yet."""
|
||||||
if isinstance(device, Gtk.ComboBoxText):
|
device = dropdown.get_active_text()
|
||||||
device = device.get_active_text()
|
|
||||||
|
logger.debug('Selecting device "%s"', device)
|
||||||
|
|
||||||
self.selected_device = device
|
self.selected_device = device
|
||||||
self.selected_preset = None
|
self.selected_preset = None
|
||||||
@ -142,7 +142,8 @@ class Window:
|
|||||||
presets = get_presets(device)
|
presets = get_presets(device)
|
||||||
if len(presets) == 0:
|
if len(presets) == 0:
|
||||||
create_preset(device)
|
create_preset(device)
|
||||||
|
else:
|
||||||
|
logger.debug('Presets for "%s": %s', device, ', '.join(presets))
|
||||||
self.populate_presets()
|
self.populate_presets()
|
||||||
|
|
||||||
def on_create_preset_clicked(self, button):
|
def on_create_preset_clicked(self, button):
|
||||||
@ -152,10 +153,10 @@ class Window:
|
|||||||
self.get('preset_selection').set_active_id(new_preset)
|
self.get('preset_selection').set_active_id(new_preset)
|
||||||
self.update_config()
|
self.update_config()
|
||||||
|
|
||||||
def on_select_preset(self, preset):
|
def on_select_preset(self, dropdown):
|
||||||
"""Show the mappings of the preset"""
|
"""Show the mappings of the preset."""
|
||||||
if isinstance(preset, Gtk.ComboBoxText):
|
preset = dropdown.get_active_text()
|
||||||
preset = preset.get_active_text()
|
logger.debug('Selecting preset "%s"', preset)
|
||||||
|
|
||||||
self.selected_preset = preset
|
self.selected_preset = preset
|
||||||
self.mappings = []
|
self.mappings = []
|
||||||
|
@ -49,16 +49,16 @@ def get_keycode(device, letter):
|
|||||||
def generate_setxkbmap_config(device, preset, mappings):
|
def generate_setxkbmap_config(device, preset, mappings):
|
||||||
"""Generate a config file for setxkbmap.
|
"""Generate a config file for setxkbmap.
|
||||||
|
|
||||||
The file is created in ~/.config/key-mapper/<device>/<preset> and
|
The file is created in ~/.config/key-mapper/<device>/<preset> and,
|
||||||
a symlink is created in
|
in order to find all presets in the home dir to make backing them up
|
||||||
/usr/share/X11/xkb/symbols/key-mapper/<device>/<preset> to point to it
|
more intuitive, a symlink is created in
|
||||||
|
/usr/share/X11/xkb/symbols/key-mapper/<device>/<preset> to point to it.
|
||||||
|
The file in home doesn't have underscore to be more beautiful on the
|
||||||
|
frontend, while the symlink doesn't contain any whitespaces.
|
||||||
"""
|
"""
|
||||||
# setxkbmap cannot handle spaces
|
|
||||||
device = device.replace(' ', '_')
|
|
||||||
preset = preset.replace(' ', '_')
|
|
||||||
|
|
||||||
config_path = os.path.join(CONFIG_PATH, device, preset)
|
config_path = os.path.join(CONFIG_PATH, device, preset)
|
||||||
usr_path = os.path.join(SYMBOLS_PATH, device, preset)
|
# setxkbmap cannot handle spaces
|
||||||
|
usr_path = os.path.join(SYMBOLS_PATH, device, preset).replace(' ', '_')
|
||||||
|
|
||||||
if not os.path.exists(config_path):
|
if not os.path.exists(config_path):
|
||||||
logger.info('Creating config file "%s"', config_path)
|
logger.info('Creating config file "%s"', config_path)
|
||||||
@ -72,12 +72,11 @@ def generate_setxkbmap_config(device, preset, mappings):
|
|||||||
with open(config_path, 'w') as f:
|
with open(config_path, 'w') as f:
|
||||||
f.write(generate_symbols_file_content(device, preset, mappings))
|
f.write(generate_symbols_file_content(device, preset, mappings))
|
||||||
|
|
||||||
logger.debug('Successfully wrote the config file')
|
|
||||||
|
|
||||||
|
|
||||||
def generate_symbols_file_content(device, preset, mappings):
|
def generate_symbols_file_content(device, preset, mappings):
|
||||||
"""Create config contents to be placed in /usr/share/X11/xkb/symbols."""
|
"""Create config contents to be placed in /usr/share/X11/xkb/symbols."""
|
||||||
system_default = 'us' # TODO get the system default
|
system_default = 'us' # TODO get the system default
|
||||||
|
# TODO I think I also have to create a file in /usr/share/X11/xkb/keycodes
|
||||||
result = '\n'.join([
|
result = '\n'.join([
|
||||||
'default xkb_symbols "basic" {',
|
'default xkb_symbols "basic" {',
|
||||||
' minimum = 8;',
|
' minimum = 8;',
|
||||||
|
@ -1,220 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# key-mapper - GUI for device specific keyboard mappings
|
|
||||||
# Copyright (C) 2020 sezanzeb <proxima@hip70890b.de>
|
|
||||||
#
|
|
||||||
# This file is part of key-mapper.
|
|
||||||
#
|
|
||||||
# key-mapper is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# key-mapper is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
"""Query settings, parse and write config files."""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from keymapper.logger import logger
|
|
||||||
|
|
||||||
|
|
||||||
# one config file per preset, one folder per device
|
|
||||||
_configs = {}
|
|
||||||
|
|
||||||
|
|
||||||
_defaults = {}
|
|
||||||
|
|
||||||
|
|
||||||
# TODO this works on xmodmaps instead of config files
|
|
||||||
|
|
||||||
|
|
||||||
def _modify_config(config_contents, key, value):
|
|
||||||
"""Return a string representing the modified contents of the config file.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
config_contents : string
|
|
||||||
Contents of the config file in ~/.config/key-mapper/config.
|
|
||||||
It is not edited in place and the config file is not overwritten.
|
|
||||||
key : string
|
|
||||||
Settings key that should be modified
|
|
||||||
value : string, int
|
|
||||||
Value to write
|
|
||||||
"""
|
|
||||||
logger.info('Setting "%s" to "%s"', key, value)
|
|
||||||
|
|
||||||
split = config_contents.split('\n')
|
|
||||||
if split[-1] == '':
|
|
||||||
split = split[:-1]
|
|
||||||
|
|
||||||
found = False
|
|
||||||
setting = f'{key}={value}'
|
|
||||||
for i, line in enumerate(split):
|
|
||||||
strip = line.strip()
|
|
||||||
if strip.startswith('#'):
|
|
||||||
continue
|
|
||||||
if strip.startswith(f'{key}='):
|
|
||||||
# replace the setting
|
|
||||||
logger.debug('Overwriting "%s=%s" in config', key, value)
|
|
||||||
split[i] = setting
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
if not found:
|
|
||||||
logger.debug('Adding "%s=%s" to config', key, value)
|
|
||||||
split.append(setting)
|
|
||||||
return '\n'.join(split)
|
|
||||||
|
|
||||||
|
|
||||||
def get_config_path(device, preset=None, path=None):
|
|
||||||
"""Get the path that leads to the coniguration of that preset.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
device : string
|
|
||||||
preset : string or None
|
|
||||||
If none, will return the folder of the device
|
|
||||||
path : string or None
|
|
||||||
If none, will default to '~/.config/key-mapper/'.
|
|
||||||
In that directory, a folder for the device and a file for
|
|
||||||
the preset will be created.
|
|
||||||
"""
|
|
||||||
path = path or os.path.expanduser('~/.config/key-mapper/')
|
|
||||||
return os.path.join(path, device, preset or '')
|
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
|
||||||
"""Read and set config values."""
|
|
||||||
def __init__(self, device, preset, path=None):
|
|
||||||
"""Initialize the interface to the config file.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
device : string
|
|
||||||
preset : string
|
|
||||||
path : string or None
|
|
||||||
If none, will default to '~/.config/key-mapper/'.
|
|
||||||
In that directory, a folder for the device and a file for
|
|
||||||
the preset will be created.
|
|
||||||
"""
|
|
||||||
path = get_config_path(device, preset, path)
|
|
||||||
logger.debug('Using config file at %s', path)
|
|
||||||
|
|
||||||
self.device = device
|
|
||||||
self.preset = preset
|
|
||||||
self._path = path
|
|
||||||
self._config = {}
|
|
||||||
self.mtime = 0
|
|
||||||
|
|
||||||
self.create_config_file()
|
|
||||||
|
|
||||||
self.load_config()
|
|
||||||
|
|
||||||
def create_config_file(self):
|
|
||||||
"""Create an empty config if it doesn't exist."""
|
|
||||||
if not os.path.exists(os.path.dirname(self._path)):
|
|
||||||
os.makedirs(os.path.dirname(self._path))
|
|
||||||
if not os.path.exists(self._path):
|
|
||||||
logger.info('Creating config file "%s"', self._path)
|
|
||||||
os.mknod(self._path)
|
|
||||||
|
|
||||||
def load_config(self):
|
|
||||||
"""Read the config file."""
|
|
||||||
logger.debug('Loading configuration')
|
|
||||||
self._config = {}
|
|
||||||
# load config
|
|
||||||
self.mtime = os.path.getmtime(self._path)
|
|
||||||
with open(self._path, 'r') as config_file:
|
|
||||||
for line in config_file:
|
|
||||||
line = line.strip()
|
|
||||||
if not line.startswith('#'):
|
|
||||||
split = line.split('=', 1)
|
|
||||||
if len(split) == 2:
|
|
||||||
key = split[0]
|
|
||||||
value = split[1]
|
|
||||||
else:
|
|
||||||
key = split[0]
|
|
||||||
value = None
|
|
||||||
if value.isdigit():
|
|
||||||
value = int(value)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
value = float(value)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
if value == 'True':
|
|
||||||
value = True
|
|
||||||
if value == 'False':
|
|
||||||
value = False
|
|
||||||
self._config[key] = value
|
|
||||||
|
|
||||||
def check_mtime(self):
|
|
||||||
"""Check if the config file has been modified and reload if needed."""
|
|
||||||
if os.path.getmtime(self._path) != self.mtime:
|
|
||||||
logger.info('Config changed, reloading')
|
|
||||||
self.load_config()
|
|
||||||
|
|
||||||
def get(self, key):
|
|
||||||
"""Read a value from the configuration or get the default."""
|
|
||||||
self.check_mtime()
|
|
||||||
return self._config.get(key, _defaults[key])
|
|
||||||
|
|
||||||
def set(self, key, value):
|
|
||||||
"""Write a setting into memory and ~/.config/key-mapper/."""
|
|
||||||
self.check_mtime()
|
|
||||||
|
|
||||||
if key in self._config and self._config[key] == value:
|
|
||||||
logger.debug('Setting "%s" is already "%s"', key, value)
|
|
||||||
return False
|
|
||||||
|
|
||||||
self._config[key] = value
|
|
||||||
|
|
||||||
with open(self._path, 'r+') as config_file:
|
|
||||||
config_contents = config_file.read()
|
|
||||||
config_contents = _modify_config(config_contents, key, value)
|
|
||||||
|
|
||||||
# overwrite completely
|
|
||||||
with open(self._path, 'w') as config_file:
|
|
||||||
if not config_contents.endswith('\n'):
|
|
||||||
config_contents += '\n'
|
|
||||||
config_file.write(config_contents)
|
|
||||||
|
|
||||||
self.mtime = os.path.getmtime(self._path)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def get_config(device, preset, path=None):
|
|
||||||
"""Ask for a config object.
|
|
||||||
|
|
||||||
There should not be multiple Config objects for the same preset, so make
|
|
||||||
sure to use this function insted of the Config constructor.
|
|
||||||
|
|
||||||
Creates a config file if it doesn't exist yet.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
device : string
|
|
||||||
preset : string
|
|
||||||
path : string or None
|
|
||||||
If none, will default to '~/.config/key-mapper/'.
|
|
||||||
In that directory, a folder for the device and a file for
|
|
||||||
the preset will be created.
|
|
||||||
"""
|
|
||||||
# don't initialize it right away in the global scope, to avoid having
|
|
||||||
# the wrong logging verbosity.
|
|
||||||
global _configs
|
|
||||||
if _configs.get(device) is None:
|
|
||||||
_configs[device] = {}
|
|
||||||
|
|
||||||
if _configs[device].get(preset) is None:
|
|
||||||
_configs[device][preset] = Config(device, preset, path)
|
|
||||||
|
|
||||||
return _configs[device][preset]
|
|
@ -29,8 +29,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from keymapper.paths import CONFIG_PATH, SYMBOLS_PATH
|
from keymapper.paths import CONFIG_PATH, SYMBOLS_PATH
|
||||||
from keymapper.logger import logger
|
from keymapper.logger import logger
|
||||||
from keymapper.config import get_config, get_config_path
|
from keymapper.X import find_devices, generate_setxkbmap_config
|
||||||
from keymapper.X import find_devices
|
|
||||||
|
|
||||||
|
|
||||||
def get_presets(device):
|
def get_presets(device):
|
||||||
@ -40,11 +39,10 @@ def get_presets(device):
|
|||||||
----------
|
----------
|
||||||
device : string
|
device : string
|
||||||
"""
|
"""
|
||||||
device_folder = os.path.join(SYMBOLS_PATH, device.replace(' ', '_'))
|
device_folder = os.path.join(CONFIG_PATH, device)
|
||||||
if not os.path.exists(device_folder):
|
if not os.path.exists(device_folder):
|
||||||
os.makedirs(get_config_path(device_folder))
|
os.makedirs(device_folder)
|
||||||
presets = os.listdir(get_config_path(device_folder))
|
presets = os.listdir(device_folder)
|
||||||
logger.debug('Presets in "%s": %s', device_folder, ', '.join(presets))
|
|
||||||
return presets
|
return presets
|
||||||
|
|
||||||
|
|
||||||
@ -58,10 +56,9 @@ def create_preset(device, name=None):
|
|||||||
i = 1
|
i = 1
|
||||||
while name in existing_names:
|
while name in existing_names:
|
||||||
i += 1
|
i += 1
|
||||||
name = f'new preset {i}'
|
name = f'{name} {i}'
|
||||||
|
|
||||||
# trigger the creation of a new config file:
|
generate_setxkbmap_config(device, name, [])
|
||||||
get_config(device, name)
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
@ -76,41 +73,43 @@ def get_mappings(device, preset):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_any_preset():
|
||||||
|
"""Return the first found tuple of (device, preset)."""
|
||||||
|
any_device = list(find_devices().keys())[0]
|
||||||
|
any_preset = (get_presets(any_device) or [None])[0]
|
||||||
|
return any_device, any_preset
|
||||||
|
|
||||||
|
|
||||||
def find_newest_preset():
|
def find_newest_preset():
|
||||||
"""Get a tuple of (device, preset) that was most recently modified.
|
"""Get a tuple of (device, preset) that was most recently modified.
|
||||||
|
|
||||||
If no device has been configured yet, return arbitrarily.
|
If no device has been configured yet, return arbitrarily.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# sort the oldest files to the front
|
# sort the oldest files to the front
|
||||||
paths = sorted(
|
paths = sorted(
|
||||||
glob.glob(os.path.join(SYMBOLS_PATH, '*/*')),
|
glob.glob(os.path.join(CONFIG_PATH, '*/*')),
|
||||||
key=os.path.getmtime
|
key=os.path.getmtime
|
||||||
)
|
)
|
||||||
|
|
||||||
# map "vendor_keyboard" to "vendor keyboard"
|
if len(paths) == 0:
|
||||||
device_mapping = {
|
logger.debug('No presets found.')
|
||||||
name.replace(' ', '_'): name
|
return get_any_preset()
|
||||||
for name in find_devices().keys()
|
|
||||||
}
|
online_devices = find_devices().keys()
|
||||||
|
|
||||||
newest_path = None
|
newest_path = None
|
||||||
while len(paths) > 0:
|
while len(paths) > 0:
|
||||||
# take the newest path
|
# take the newest path
|
||||||
path = paths.pop()
|
path = paths.pop()
|
||||||
preset = os.path.split(path)[1]
|
preset = os.path.split(path)[1]
|
||||||
device_underscored = os.path.split(os.path.split(path)[0])[1]
|
device = os.path.split(os.path.split(path)[0])[1]
|
||||||
if device_mapping.get(device_underscored) is not None:
|
if device in online_devices:
|
||||||
# this device is online
|
|
||||||
newest_path = path
|
newest_path = path
|
||||||
break
|
break
|
||||||
|
|
||||||
if newest_path is None:
|
if newest_path is None:
|
||||||
logger.debug('None of the configured devices is currently online.')
|
logger.debug('None of the configured devices is currently online.')
|
||||||
# return anything
|
return get_any_preset()
|
||||||
device = list(find_devices().keys())[0]
|
|
||||||
preset = (get_presets(device) or [None])[0]
|
|
||||||
return device, preset
|
|
||||||
|
|
||||||
device = device_mapping.get(device_underscored)
|
|
||||||
|
|
||||||
return device, preset
|
return device, preset
|
||||||
|
@ -25,29 +25,21 @@
|
|||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
# quickly fake some stuff before any other file gets imported and initialized
|
||||||
from keymapper import paths
|
from keymapper import paths
|
||||||
|
paths.SYMBOLS_PATH = '/tmp/key-mapper-test/symbols'
|
||||||
|
paths.CONFIG_PATH = '/tmp/key-mapper-test/.config'
|
||||||
|
|
||||||
from keymapper import X
|
from keymapper import X
|
||||||
|
X.find_devices = lambda: ({
|
||||||
|
'device 1': ['/dev/input/event10', '/dev/input/event11'],
|
||||||
|
'device 2': ['/dev/input/event3']
|
||||||
|
})
|
||||||
|
|
||||||
from keymapper.logger import update_verbosity
|
from keymapper.logger import update_verbosity
|
||||||
|
|
||||||
|
|
||||||
def create_stubs():
|
|
||||||
"""Stub some linux stuff."""
|
|
||||||
paths.SYMBOLS_PATH = '/tmp/key-mapper-test/symbols'
|
|
||||||
paths.CONFIG_PATH = '/tmp/key-mapper-test/.config'
|
|
||||||
|
|
||||||
def find_devices():
|
|
||||||
return {
|
|
||||||
'device 1': ['/dev/input/event10', '/dev/input/event11'],
|
|
||||||
'device 2': ['/dev/input/event3']
|
|
||||||
}
|
|
||||||
|
|
||||||
X.find_devices = find_devices
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# make sure to do this before any other file gets a chance to do imports
|
|
||||||
create_stubs()
|
|
||||||
|
|
||||||
update_verbosity(True)
|
update_verbosity(True)
|
||||||
|
|
||||||
modules = sys.argv[1:]
|
modules = sys.argv[1:]
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# key-mapper - GUI for device specific keyboard mappings
|
|
||||||
# Copyright (C) 2020 sezanzeb <proxima@hip70890b.de>
|
|
||||||
#
|
|
||||||
# This file is part of key-mapper.
|
|
||||||
#
|
|
||||||
# key-mapper is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# key-mapper is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from keymapper.logger import update_verbosity
|
|
||||||
from keymapper.config import _modify_config, get_config
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigTest(unittest.TestCase):
|
|
||||||
def test_first_line(self):
|
|
||||||
contents = """a=1\n # test=3\n abc=123"""
|
|
||||||
contents = _modify_config(contents, 'a', 3)
|
|
||||||
self.assertEqual(contents, """a=3\n # test=3\n abc=123""")
|
|
||||||
|
|
||||||
def test_last_line(self):
|
|
||||||
contents = """a=1\n # test=3\n abc=123"""
|
|
||||||
contents = _modify_config(contents, 'abc', 'foo')
|
|
||||||
self.assertEqual(contents, """a=1\n # test=3\nabc=foo""")
|
|
||||||
|
|
||||||
def test_new_line(self):
|
|
||||||
contents = """a=1\n # test=3\n abc=123"""
|
|
||||||
contents = _modify_config(contents, 'test', '1234')
|
|
||||||
self.assertEqual(contents, """a=1\n # test=3\n abc=123\ntest=1234""")
|
|
||||||
|
|
||||||
def test_get_config(self):
|
|
||||||
config = get_config('device1', 'preset1', '/tmp/key-mapper')
|
|
||||||
self.assertEqual(config.device, 'device1')
|
|
||||||
self.assertEqual(config.preset, 'preset1')
|
|
||||||
self.assertTrue(os.path.isfile('/tmp/key-mapper/device1/preset1'))
|
|
||||||
|
|
||||||
get_config('device1', 'preset2', '/tmp/key-mapper')
|
|
||||||
self.assertTrue(os.path.isfile('/tmp/key-mapper/device1/preset2'))
|
|
||||||
|
|
||||||
get_config('device2', 'preset3', '/tmp/key-mapper')
|
|
||||||
self.assertTrue(os.path.isfile('/tmp/key-mapper/device2/preset3'))
|
|
||||||
|
|
||||||
config.set('key1', 'value')
|
|
||||||
config.set('key2', 123)
|
|
||||||
with open('/tmp/key-mapper/device1/preset1', 'r') as f:
|
|
||||||
contents = f.read()
|
|
||||||
self.assertEqual(contents, 'key1=value\nkey2=123\n')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
@ -19,7 +19,6 @@
|
|||||||
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
|
# along with key-mapper. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
@ -27,12 +26,10 @@ from importlib.util import spec_from_loader, module_from_spec
|
|||||||
from importlib.machinery import SourceFileLoader
|
from importlib.machinery import SourceFileLoader
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
|
import shutil
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
from fakes import UseFakes, fake_config_path
|
|
||||||
from keymapper.config import get_config
|
|
||||||
|
|
||||||
|
|
||||||
def gtk_iteration():
|
def gtk_iteration():
|
||||||
"""Iterate while events are pending."""
|
"""Iterate while events are pending."""
|
||||||
@ -74,17 +71,13 @@ class Integration(unittest.TestCase):
|
|||||||
Gtk.main_quit = lambda: None
|
Gtk.main_quit = lambda: None
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.fakes = UseFakes()
|
|
||||||
self.fakes.patch()
|
|
||||||
self.window = launch()
|
self.window = launch()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.window.on_close()
|
self.window.on_close()
|
||||||
self.window.window.destroy()
|
self.window.window.destroy()
|
||||||
gtk_iteration()
|
gtk_iteration()
|
||||||
self.fakes.restore()
|
shutil.rmtree('/tmp/key-mapper-test')
|
||||||
# TODO iterate over all config files in the fake_path and
|
|
||||||
# empty them
|
|
||||||
|
|
||||||
def test_can_start(self):
|
def test_can_start(self):
|
||||||
self.assertIsNotNone(self.window)
|
self.assertIsNotNone(self.window)
|
||||||
|
@ -24,47 +24,69 @@ import unittest
|
|||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from keymapper.presets import find_newest_preset
|
from keymapper.presets import find_newest_preset, create_preset
|
||||||
|
|
||||||
|
|
||||||
class PresetsTest(unittest.TestCase):
|
tmp = '/tmp/key-mapper-test'
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreatePreset(unittest.TestCase):
|
||||||
|
def test_create_preset_1(self):
|
||||||
|
create_preset('device 1')
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/symbols/device_1/new_preset'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/.config/device 1/new preset'))
|
||||||
|
|
||||||
|
def test_create_preset_2(self):
|
||||||
|
create_preset('device 1')
|
||||||
|
create_preset('device 1')
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/symbols/device_1/new_preset'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/.config/device 1/new preset'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/symbols/device_1/new_preset_2'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/.config/device 1/new preset 2'))
|
||||||
|
|
||||||
|
def test_create_preset_3(self):
|
||||||
|
create_preset('device 1', 'pre set')
|
||||||
|
create_preset('device 1', 'pre set')
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/symbols/device_1/pre_set'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/.config/device 1/pre set'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/symbols/device_1/pre_set_2'))
|
||||||
|
self.assertTrue(os.path.exists(f'{tmp}/.config/device 1/pre set 2'))
|
||||||
|
|
||||||
|
|
||||||
|
class TestFindPresets(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
shutil.rmtree('/tmp/key-mapper-test')
|
shutil.rmtree(f'{tmp}')
|
||||||
|
|
||||||
def test_find_newest_preset_1(self):
|
def test_find_newest_preset_1(self):
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_1')
|
print('test_find_newest_preset_1')
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_2')
|
create_preset('device 1', 'preset 1')
|
||||||
os.mknod('/tmp/key-mapper-test/symbols/device_1/preset_1')
|
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
os.mknod('/tmp/key-mapper-test/symbols/device_2/preset_2')
|
create_preset('device 2', 'preset 2')
|
||||||
# since presets are loaded from the path, and devices from the
|
self.assertEqual(find_newest_preset(), ('device 2', 'preset 2'))
|
||||||
# x command line tools, the presets have the exact same name as
|
|
||||||
# the path whereas devices need their whitespaces removed.
|
|
||||||
self.assertEqual(find_newest_preset(), ('device 2', 'preset_2'))
|
|
||||||
|
|
||||||
def test_find_newest_preset_2(self):
|
def test_find_newest_preset_2(self):
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_1')
|
os.makedirs(f'{tmp}/symbols/device_1')
|
||||||
|
os.makedirs(f'{tmp}/.config/device_1')
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_2')
|
os.makedirs(f'{tmp}/symbols/device_2')
|
||||||
|
os.makedirs(f'{tmp}/.config/device_2')
|
||||||
# takes the first one that the test-fake returns
|
# takes the first one that the test-fake returns
|
||||||
self.assertEqual(find_newest_preset(), ('device 1', None))
|
self.assertEqual(find_newest_preset(), ('device 1', None))
|
||||||
|
|
||||||
def test_find_newest_preset_3(self):
|
def test_find_newest_preset_3(self):
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_1')
|
os.makedirs(f'{tmp}/symbols/device_1')
|
||||||
|
os.makedirs(f'{tmp}/.config/device_1')
|
||||||
self.assertEqual(find_newest_preset(), ('device 1', None))
|
self.assertEqual(find_newest_preset(), ('device 1', None))
|
||||||
|
|
||||||
def test_find_newest_preset_4(self):
|
def test_find_newest_preset_4(self):
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_1')
|
create_preset('device 1', 'preset 1')
|
||||||
os.mknod('/tmp/key-mapper-test/symbols/device_1/preset_1')
|
self.assertEqual(find_newest_preset(), ('device 1', 'preset 1'))
|
||||||
self.assertEqual(find_newest_preset(), ('device 1', 'preset_1'))
|
|
||||||
|
|
||||||
def test_find_newest_preset_5(self):
|
def test_find_newest_preset_5(self):
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/device_1')
|
create_preset('device 1', 'preset 1')
|
||||||
os.mknod('/tmp/key-mapper-test/symbols/device_1/preset_1')
|
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
os.makedirs('/tmp/key-mapper-test/symbols/unknown_device3')
|
create_preset('unknown device 3', 'preset 3')
|
||||||
os.mknod('/tmp/key-mapper-test/symbols/unknown_device3/preset_1')
|
self.assertEqual(find_newest_preset(), ('device 1', 'preset 1'))
|
||||||
self.assertEqual(find_newest_preset(), ('device 1', 'preset_1'))
|
|
||||||
|
|
||||||
def test_find_newest_preset_6(self):
|
def test_find_newest_preset_6(self):
|
||||||
# takes the first one that the test-fake returns
|
# takes the first one that the test-fake returns
|
||||||
|
Loading…
Reference in New Issue
Block a user