Co-authored-by: jonasBoss <jonas.bosse@posteo.de>
2.0.0-rc_mypy
Tobi 1 year ago committed by GitHub
parent 4c41f8c9e0
commit de0dd8af8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,5 @@
Package: input-remapper
Version: 1.6.0-beta
Version: 2.0.0-rc
Architecture: all
Maintainer: Sezanzeb <proxima@sezanzeb.de>
Depends: build-essential, libpython3-dev, libdbus-1-dev, python3, python3-setuptools, python3-evdev, python3-pydbus, python3-gi, gettext, python3-cairo, libgtk-3-0, libgtksourceview-4-dev, python3-pydantic

@ -1,6 +1,6 @@
<p align="center"><img src="data/input-remapper.svg" width=100/></p>
<h1 align="center">Input Remapper (Beta)</h1>
<h1 align="center">Input Remapper</h1>
<p align="center">
An easy to use tool to change the behaviour of your input devices.<br/>
@ -14,9 +14,9 @@
<p align="center">
<img src="readme/screenshot.png" width="49%"/>
<img src="readme/screenshot_2.png" width="49%"/>
<img src="readme/screenshot.png" width="48%"/>
&#160;
<img src="readme/screenshot_2.png" width="48%"/>
</p>
## Installation
@ -36,7 +36,7 @@ or install the latest changes via:
sudo apt install git python3-setuptools gettext
git clone https://github.com/sezanzeb/input-remapper.git
cd input-remapper && ./scripts/build.sh
sudo apt install ./dist/input-remapper-1.6.0-beta.deb
sudo apt install -f ./dist/input-remapper-2.0.0-rc.deb
```
input-remapper is available in [Debian](https://tracker.debian.org/pkg/input-remapper)
@ -50,6 +50,8 @@ Python packages need to be installed globally for the service to be able to impo
Conda can cause problems due to changed python paths and versions.
If it doesn't seem to install, you can also try `sudo python3 setup.py install`
```bash
sudo pip install evdev -U # If newest version not in distros repo
sudo pip uninstall key-mapper # In case the old package is still installed
@ -58,11 +60,14 @@ sudo systemctl enable input-remapper
sudo systemctl restart input-remapper
```
If it doesn't seem to install, you can also try `sudo python3 setup.py install`
## Migrating beta configs to version 2
##### Beta
By default, Input Remapper will not migrate configurations from the beta.
If you want to use those you will need to copy them manually.
The `beta` branch contains features that still require work, but that are ready for testing. It uses a different
config path, so your presets won't break. `input-remapper-beta-git` can be installed from the AUR. If you are
facing problems, please open up an [issue](https://github.com/sezanzeb/input-remapper/issues).
```bash
rm ~/.config/input-remapper-2 -r
cp ~/.config/input-remapper/beta_1.6.0-beta ~/.config/input-remapper-2 -r
```
Then start input-remapper

@ -54,7 +54,7 @@ from inputremapper.configs.preset import Preset
from inputremapper.configs.system_mapping import system_mapping
from inputremapper.injection.global_uinputs import global_uinputs
from inputremapper.injection.macros.parse import is_this_a_macro
from inputremapper.logger import logger, VERSION, IS_BETA
from inputremapper.logger import logger, VERSION
from inputremapper.user import HOME
@ -169,12 +169,12 @@ def _update_version():
json.dump(config, file, indent=4)
def _rename_config(new_path=CONFIG_PATH):
def _rename_to_input_remapper():
"""Rename .config/key-mapper to .config/input-remapper."""
old_config_path = os.path.join(HOME, ".config/key-mapper")
if not os.path.exists(new_path) and os.path.exists(old_config_path):
logger.info("Moving %s to %s", old_config_path, new_path)
shutil.move(old_config_path, new_path)
if not os.path.exists(CONFIG_PATH) and os.path.exists(old_config_path):
logger.info("Moving %s to %s", old_config_path, CONFIG_PATH)
shutil.move(old_config_path, CONFIG_PATH)
def _find_target(symbol):
@ -429,19 +429,31 @@ def _convert_to_individual_mappings():
migrated_preset.save()
def _copy_to_beta():
if os.path.exists(CONFIG_PATH) or not IS_BETA:
def _copy_to_v2():
"""Move the beta config to the v2 path, or copy the v1 config to the v2 path."""
# TODO test
if os.path.exists(CONFIG_PATH):
# don't copy to already existing folder
# users should delete the beta folder if they need to
# users should delete the input-remapper-2 folder if they need to
return
regular_path = os.path.join(*os.path.split(CONFIG_PATH)[:-1])
# workaround to maker sure the rename from key-mapper to input-remapper
# does not move everythig to the beta folder
_rename_config(regular_path)
if os.path.exists(regular_path):
logger.debug("copying all from %s to %s", regular_path, CONFIG_PATH)
shutil.copytree(regular_path, CONFIG_PATH)
# prioritize the v1 configs over beta configs
old_path = os.path.join(HOME, ".config/input-remapper")
if os.path.exists(os.path.join(old_path, "config.json")):
# no beta path, only old presets exist. COPY to v2 path, which will then be
# migrated by the various migrations.
logger.debug("copying all from %s to %s", old_path, CONFIG_PATH)
shutil.copytree(old_path, CONFIG_PATH)
return
# if v1 configs don't exist, try to find beta configs.
beta_path = os.path.join(HOME, ".config/input-remapper/beta_1.6.0-beta")
if os.path.exists(beta_path):
# There has never been a different version than "1.6.0-beta" in beta, so we
# only need to check for that exact directory
# already migrated, possibly new presets in them, move to v2 path
logger.debug("moving %s to %s", beta_path, CONFIG_PATH)
shutil.move(beta_path, CONFIG_PATH)
def _remove_logs():
@ -459,8 +471,12 @@ def _remove_logs():
def migrate():
"""Migrate config files to the current release."""
_copy_to_beta()
_rename_to_input_remapper()
_copy_to_v2()
v = config_version()
if v < pkg_resources.parse_version("0.4.0"):
_config_suffix()
_preset_path()
@ -468,9 +484,6 @@ def migrate():
if v < pkg_resources.parse_version("1.2.2"):
_mapping_keys()
if v < pkg_resources.parse_version("1.3.0"):
_rename_config()
if v < pkg_resources.parse_version("1.4.0"):
global_uinputs.prepare_all()
_add_target()

@ -26,12 +26,11 @@ import os
import shutil
from typing import List, Union, Optional
from inputremapper.logger import logger, VERSION, IS_BETA
from inputremapper.logger import logger, VERSION
from inputremapper.user import USER, HOME
rel_path = ".config/input-remapper"
if IS_BETA:
rel_path = os.path.join(rel_path, f"beta_{VERSION}")
rel_path = ".config/input-remapper-2"
CONFIG_PATH = os.path.join(HOME, rel_path)
@ -44,7 +43,7 @@ def chown(path):
shutil.chown(path, user=USER)
def touch(path: os.PathLike, log=True):
def touch(path: Union[str, os.PathLike], log=True):
"""Create an empty file and all its parent dirs, give it to the user."""
if str(path).endswith("/"):
raise ValueError(f"Expected path to not end with a slash: {path}")
@ -143,6 +142,6 @@ def get_preset_path(group_name: Optional[str] = None, preset: Optional[str] = No
return os.path.join(presets_base, group_name, preset)
def get_config_path(*paths):
def get_config_path(*paths) -> str:
"""Get a path in ~/.config/input-remapper/."""
return os.path.join(CONFIG_PATH, *paths)

@ -296,34 +296,17 @@ class Preset(Generic[MappingModel]):
logger.error("unable to decode json file: %s", self.path)
return mappings
if isinstance(preset_list, dict):
# todo: remove this before merge into main
# adds compatibility with older beta versions
def str_to_cfg(string):
config = []
for event_str in string.split("+"):
type_, code, analog_threshold = event_str.split(",")
config.append(
{
"type": type_,
"code": code,
"analog_threshold": analog_threshold,
}
)
return config
for combination_string, mapping_dict in preset_list.items():
mapping_dict["input_combination"] = str_to_cfg(combination_string)
preset_list = list(preset_list.values())
for mapping_dict in preset_list:
if not isinstance(mapping_dict, dict):
logger.error("Expected mapping to be a dict: %s", mapping_dict)
continue
try:
mapping = self._mapping_factory(**mapping_dict)
except ValidationError as error:
print(mapping_dict)
except Exception as error:
logger.error(
"failed to Validate mapping for %s: %s",
mapping_dict["input_combination"],
mapping_dict.get("input_combination"),
error,
)
continue

@ -244,7 +244,7 @@ logging.getLogger("asyncio").setLevel(logging.WARNING)
# using pkg_resources to figure out the version fails in many cases,
# so we hardcode it instead
VERSION = "1.6.0-beta"
VERSION = "2.0.0-rc"
EVDEV_VERSION = None
try:
EVDEV_VERSION = pkg_resources.require("evdev")[0].version

@ -72,7 +72,7 @@ ssh/login into a debian/ubuntu environment
./scripts/build.sh
```
This will generate `input-remapper/deb/input-remapper-1.6.0-beta.deb`
This will generate `input-remapper/deb/input-remapper-2.0.0-rc.deb`
## Badges
@ -121,3 +121,4 @@ https://miro.com/app/board/uXjVPLa8ilM=/?share_link_id=272180986764
- [GNOME HIG](https://developer.gnome.org/hig/stable/)
- [GtkSource Example](https://github.com/wolfthefallen/py-GtkSourceCompletion-example)
- [linux/input-event-codes.h](https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h)
- [Screenshot Guidelines](https://www.freedesktop.org/software/appstream/docs/chap-Quickstart.html)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 64 KiB

@ -9,8 +9,8 @@ build_deb() {
mv build/deb/usr/local/lib/python3.*/ build/deb/usr/lib/python3/
cp ./DEBIAN build/deb/ -r
mkdir dist -p
rm dist/input-remapper-1.6.0-beta.deb || true
dpkg-deb -Z gzip -b build/deb dist/input-remapper-1.6.0-beta.deb
rm dist/input-remapper-2.0.0-rc.deb || true
dpkg-deb -Z gzip -b build/deb dist/input-remapper-2.0.0-rc.deb
}
build_deb &

@ -102,7 +102,7 @@ for po_file in glob.glob(PO_FILES):
setup(
name="input-remapper",
version="1.6.0-beta",
version="2.0.0-rc",
description="A tool to change the mapping of your input device buttons",
author="Sezanzeb",
author_email="proxima@sezanzeb.de",

@ -35,14 +35,21 @@ from evdev.ecodes import (
REL_Y,
REL_WHEEL_HI_RES,
REL_HWHEEL_HI_RES,
KEY_A,
)
from inputremapper.configs.mapping import UIMapping
from inputremapper.configs.migrations import migrate, config_version
from inputremapper.configs.preset import Preset
from inputremapper.configs.global_config import global_config
from inputremapper.configs.paths import touch, CONFIG_PATH, mkdir, get_preset_path
from inputremapper.logger import IS_BETA
from inputremapper.configs.paths import (
touch,
CONFIG_PATH,
mkdir,
get_preset_path,
get_config_path,
remove,
)
from inputremapper.configs.input_config import InputCombination, InputConfig
from inputremapper.user import HOME
@ -50,6 +57,20 @@ from inputremapper.logger import VERSION
class TestMigrations(unittest.TestCase):
def setUp(self):
# some extra care to ensure those tests are not destroying actual presets
self.assertTrue(HOME.startswith("/tmp"))
self.assertTrue(CONFIG_PATH.startswith("/tmp"))
self.assertTrue(get_preset_path().startswith("/tmp"))
self.assertTrue(get_preset_path("foo", "bar").startswith("/tmp"))
self.assertTrue(get_config_path().startswith("/tmp"))
self.assertTrue(get_config_path("foo").startswith("/tmp"))
self.v1_dir = os.path.join(HOME, ".config", "input-remapper")
self.beta_dir = os.path.join(
HOME, ".config", "input-remapper", "beta_1.6.0-beta"
)
def tearDown(self):
quick_cleanup()
self.assertEqual(len(global_config.iterate_autoload_presets()), 0)
@ -73,10 +94,7 @@ class TestMigrations(unittest.TestCase):
def test_rename_config(self):
old = os.path.join(HOME, ".config", "key-mapper")
if IS_BETA:
new = os.path.join(*os.path.split(CONFIG_PATH)[:-1])
else:
new = CONFIG_PATH
new = CONFIG_PATH
# we are not destroying our actual config files with this test
self.assertTrue(new.startswith(tmp), f'Expected "{new}" to start with "{tmp}"')
@ -553,6 +571,136 @@ class TestMigrations(unittest.TestCase):
),
)
def _create_v1_setup(self):
"""Create all files needed to mimic an outdated v1 configuration."""
device_name = "device_name"
mkdir(os.path.join(self.v1_dir, "presets", device_name))
v1_config = {"autoload": {device_name: "foo"}, "version": "1.0"}
with open(os.path.join(self.v1_dir, "config.json"), "w") as file:
json.dump(v1_config, file)
# insert something outdated that will be migrated, to ensure the files are
# first copied and then migrated.
with open(
os.path.join(self.v1_dir, "presets", device_name, "foo.json"), "w"
) as file:
json.dump({"mapping": {f"{EV_KEY},1": "a"}}, file)
def _create_beta_setup(self):
"""Create all files needed to mimic a beta configuration."""
device_name = "device_name"
# same here, but a different contents to tell the difference
mkdir(os.path.join(self.beta_dir, "presets", device_name))
beta_config = {"autoload": {device_name: "bar"}, "version": "1.6"}
with open(os.path.join(self.beta_dir, "config.json"), "w") as file:
json.dump(beta_config, file)
with open(
os.path.join(self.beta_dir, "presets", device_name, "bar.json"), "w"
) as file:
json.dump(
[
{
"input_combination": [
{"type": EV_KEY, "code": 1},
],
"target_uinput": "keyboard",
"output_symbol": "b",
"mapping_type": "key_macro",
}
],
file,
)
def test_prioritize_v1_over_beta_configs(self):
# if both v1 and beta presets and config exist, migrate v1
remove(get_config_path())
device_name = "device_name"
self._create_v1_setup()
self._create_beta_setup()
self.assertFalse(os.path.exists(get_preset_path(device_name, "foo")))
self.assertFalse(os.path.exists(get_config_path("config.json")))
migrate()
self.assertTrue(os.path.exists(get_preset_path(device_name, "foo")))
self.assertTrue(os.path.exists(get_config_path("config.json")))
self.assertFalse(os.path.exists(get_preset_path(device_name, "bar")))
# expect all original files to still exist
self.assertTrue(os.path.join(self.v1_dir, "config.json"))
self.assertTrue(os.path.join(self.v1_dir, "presets", "foo.json"))
self.assertTrue(os.path.join(self.beta_dir, "config.json"))
self.assertTrue(os.path.join(self.beta_dir, "presets", "bar.json"))
# v1 configs should be in the v2 dir now, and migrated
with open(get_config_path("config.json"), "r") as f:
config_json = json.load(f)
self.assertDictEqual(
config_json, {"autoload": {device_name: "foo"}, "version": VERSION}
)
with open(get_preset_path(device_name, "foo.json"), "r") as f:
os.system(f'cat { get_preset_path(device_name, "foo.json") }')
preset_foo_json = json.load(f)
self.assertEqual(
preset_foo_json,
[
{
"input_combination": [
{"type": EV_KEY, "code": 1},
],
"target_uinput": "keyboard",
"output_symbol": "a",
"mapping_type": "key_macro",
}
],
)
def test_copy_over_beta_configs(self):
# same as test_prioritize_v1_over_beta_configs, but only create the beta
# directory without any v1 presets.
remove(get_config_path())
device_name = "device_name"
self._create_beta_setup()
self.assertFalse(os.path.exists(get_preset_path(device_name, "bar")))
self.assertFalse(os.path.exists(get_config_path("config.json")))
migrate()
self.assertTrue(os.path.exists(get_preset_path(device_name, "bar")))
self.assertTrue(os.path.exists(get_config_path("config.json")))
# expect all original files to still exist
self.assertTrue(os.path.join(self.beta_dir, "config.json"))
self.assertTrue(os.path.join(self.beta_dir, "presets", "bar.json"))
# beta configs should be in the v2 dir now
with open(get_config_path("config.json"), "r") as f:
config_json = json.load(f)
self.assertDictEqual(
config_json, {"autoload": {device_name: "bar"}, "version": VERSION}
)
with open(get_preset_path(device_name, "bar.json"), "r") as f:
os.system(f'cat { get_preset_path(device_name, "bar.json") }')
preset_foo_json = json.load(f)
self.assertEqual(
preset_foo_json,
[
{
"input_combination": [
{"type": EV_KEY, "code": 1},
],
"target_uinput": "keyboard",
"output_symbol": "b",
"mapping_type": "key_macro",
}
],
)
if __name__ == "__main__":
unittest.main()

Loading…
Cancel
Save