Add github actions workflows (#267)

* Run linters and unit tests with github actions

* Reformat with black, 22.1.0 (compiled: yes)

* Remove native deps as should no longer be needed

* Remove pylint from workflows

* Remove unused Gtk dependency in test_daemon.py

* Install subset of python deps with apt-get for ci
pull/298/head
Luna Nova 2 years ago committed by GitHub
parent 162e7fcbf7
commit ee6b48ac32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,25 @@
name: Lint
on: [push, pull_request]
jobs:
black:
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
scripts/ci-install-deps.sh
pip install black
- name: Analysing the code with black --check --diff
run: |
black --check --diff ./inputremapper ./tests

@ -0,0 +1,46 @@
---
name: reviewdog
# run reviewdog for PR only because "github-check" option is failing :(
# https://github.com/reviewdog/reviewdog/issues/924
on: [pull_request]
jobs:
reviewdog_python:
name: reviewdog - Python lint
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- uses: reviewdog/action-setup@master
with:
reviewdog_version: latest
- name: Install dependencies
shell: bash
run: |
scripts/ci-install-deps.sh
pip install flake8 pylint mypy black
- name: Set env for PR
if: github.event_name == 'pull_request'
shell: bash
run: echo "REWIEVDOG_REPORTER=github-pr-review" >> $GITHUB_ENV
- name: Set env for push
if: github.event_name != 'pull_request'
shell: bash
run: echo "REWIEVDOG_REPORTER=github-check" >> $GITHUB_ENV
- name: Run reviewdog
shell: bash
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
reviewdog -list
reviewdog -tee -runners=mypy,black -reporter=${{ env.REWIEVDOG_REPORTER }} -fail-on-error=false

@ -0,0 +1,28 @@
name: Test
on: [push, pull_request]
jobs:
build:
continue-on-error: true
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
strategy:
matrix:
python-version: ["3.7", "3.10"] # min and max supported versions?
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
# Install deps as root since we will run tests as root
sudo scripts/ci-install-deps.sh
sudo pip install .
- name: Run tests
run: |
# FIXME: Had some permissions issues, currently worked around by running tests as root
mkdir test_tmp
TMPDIR="$(realpath test_tmp)" sudo python tests/test.py --start-dir unit

@ -0,0 +1,21 @@
---
runner:
mypy:
name: mypy
cmd: mypy --show-column-numbers inputremapper tests --ignore-missing-imports
errorformat:
- "%f:%l:%c: %m"
pylint:
name: pylint
cmd: pylint inputremapper tests --extension-pkg-whitelist=evdev
errorformat:
- "%f:%l:%c: %t%n: %m"
flake8:
cmd: flake8 inputremapper tests
format: flake8
black:
cmd: black --diff --quiet --check ./inputremapper ./tests
format: black

@ -213,7 +213,7 @@ class JoystickToMouse(Consumer):
non_linearity = preset.get("gamepad.joystick.non_linearity")
x_scroll_speed = preset.get("gamepad.joystick.x_scroll_speed")
y_scroll_speed = preset.get("gamepad.joystick.y_scroll_speed")
max_speed = 2 ** 0.5 # for normalized abs event values
max_speed = 2**0.5 # for normalized abs event values
if abs_range is not None:
logger.info(

@ -27,7 +27,9 @@ from typing import Tuple
from inputremapper.exceptions import InputEventCreationError
@dataclass(frozen=True) # Todo: add slots=True as soon as python 3.10 is in common distros
@dataclass(
frozen=True
) # Todo: add slots=True as soon as python 3.10 is in common distros
class InputEvent:
"""
the evnet used by inputremapper

@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Called from multiple CI pipelines in .github/workflows
set -xeuo pipefail
# native deps
# gettext required to generate translations, others are python deps
sudo apt-get install -y gettext python3-evdev python3-pydbus python3-pydantic
# ensure pip and setuptools/wheel up to date so can install all pip modules
python -m pip install --upgrade pip
pip install wheel setuptools
# install test deps which aren't in setup.py
pip install psutil

@ -129,13 +129,7 @@ setup(
("/usr/bin/", ["bin/key-mapper-service"]),
("/usr/bin/", ["bin/key-mapper-control"]),
],
install_requires=[
"setuptools",
"evdev",
"pydbus",
"pygobject",
"pydantic"
],
install_requires=["setuptools", "evdev", "pydbus", "pygobject", "pydantic"],
cmdclass={
"install": Install,
},

@ -0,0 +1,48 @@
# shell.nix - used with nix-shell to get a development environment with necessary dependencies
# Should be enough to run unit tests, integration tests and the service won't work
# If you don't use nix, don't worry about/use this file
let
pkgs = import <nixpkgs> { };
python = pkgs.python310;
in
pkgs.mkShell {
nativeBuildInputs = [
pkgs.pkg-config
pkgs.wrapGAppsHook
];
buildInputs = [
pkgs.gobject-introspection
pkgs.gtk3
pkgs.bashInteractive
pkgs.gobject-introspection
pkgs.xlibs.xmodmap
pkgs.gtksourceview4
(python.withPackages (
python-packages: with python-packages; [
pip
wheel
setuptools # for pkg_resources
types-setuptools
evdev
pydbus
pygobject3
pydantic
psutil # only used in tests
]
))
];
# https://nixos.wiki/wiki/Python#Emulating_virtualenv_with_nix-shell
shellHook = ''
# Tells pip to put packages into $PIP_PREFIX instead of the usual locations.
# See https://pip.pypa.io/en/stable/user_guide/#environment-variables.
export PIP_PREFIX=$(pwd)/venv
export PYTHONPATH="$PIP_PREFIX/${python.sitePackages}:$PYTHONPATH"
export PATH="$PIP_PREFIX/bin:$PATH"
unset SOURCE_DATE_EPOCH
python setup.py egg_info
pip install `grep -v '^\[' *.egg-info/requires.txt` || true
'';
}

@ -699,12 +699,18 @@ class TestGui(GuiTestBase):
def test_editor_keycode_to_string(self):
# not an integration test, but I have all the selection_label tests here already
self.assertEqual(EventCombination((EV_KEY, evdev.ecodes.KEY_A, 1)).beautify(), "a")
self.assertEqual(
EventCombination((EV_KEY, evdev.ecodes.KEY_A, 1)).beautify(), "a"
)
self.assertEqual(
EventCombination([EV_KEY, evdev.ecodes.KEY_A, 1]).beautify(), "a"
)
self.assertEqual(EventCombination((EV_ABS, evdev.ecodes.ABS_HAT0Y, -1)).beautify(), "DPad Up")
self.assertEqual(EventCombination((EV_KEY, evdev.ecodes.BTN_A, 1)).beautify(), "Button A")
self.assertEqual(
EventCombination((EV_ABS, evdev.ecodes.ABS_HAT0Y, -1)).beautify(), "DPad Up"
)
self.assertEqual(
EventCombination((EV_KEY, evdev.ecodes.BTN_A, 1)).beautify(), "Button A"
)
self.assertEqual(EventCombination((EV_KEY, 1234, 1)).beautify(), "1234")
self.assertEqual(
EventCombination([EV_ABS, evdev.ecodes.ABS_HAT0X, -1]).beautify(),
@ -1736,7 +1742,7 @@ class TestGui(GuiTestBase):
gtk_iteration()
speed = active_preset.get("gamepad.joystick.pointer_speed")
active_preset.set("gamepad.joystick.non_linearity", 1)
self.assertEqual(speed, 2 ** 6)
self.assertEqual(speed, 2**6)
# don't consume the events in the reader, they are used to test
# the injection

@ -20,6 +20,7 @@
"""Sets up inputremapper for the tests and runs them."""
import argparse
import os
import sys
import tempfile
@ -663,7 +664,15 @@ cleanup()
def main():
modules = sys.argv[1:]
# https://docs.python.org/3/library/argparse.html
parser = argparse.ArgumentParser(description=__doc__)
# repeated argument 0 or more times with modules
parser.add_argument("modules", type=str, nargs="*")
# start-dir value if not using modules, allows eg python tests/test.py --start-dir unit
parser.add_argument("--start-dir", type=str, default=".")
parsed_args = parser.parse_args() # takes from sys.argv by default
modules = parsed_args.modules
# discoverer is really convenient, but it can't find a specific test
# in all of the available tests like unittest.main() does...,
# so provide both options.
@ -674,7 +683,9 @@ def main():
testsuite = unittest.defaultTestLoader.loadTestsFromNames(modules)
else:
# run all tests by default
testsuite = unittest.defaultTestLoader.discover(".", pattern="test_*.py")
testsuite = unittest.defaultTestLoader.discover(
parsed_args.start_dir, pattern="test_*.py"
)
# add a newline to each "qux (foo.bar)..." output before each test,
# because the first log will be on the same line otherwise

@ -27,7 +27,6 @@ import json
import evdev
from evdev.ecodes import EV_KEY, EV_ABS, KEY_B, KEY_A
from gi.repository import Gtk
from pydbus import SystemBus
from inputremapper.configs.system_mapping import system_mapping
@ -51,12 +50,6 @@ from tests.test import (
)
def gtk_iteration():
"""Iterate while events are pending."""
while Gtk.events_pending():
Gtk.main_iteration()
check_output = subprocess.check_output
os_system = os.system
dbus_get = type(SystemBus()).get

@ -91,10 +91,14 @@ class TestInputEvent(unittest.TestCase):
)
self.assertEqual(e1.type_and_code, (evdev.ecodes.EV_KEY, evdev.ecodes.BTN_LEFT))
with self.assertRaises(FrozenInstanceError): # would be TypeError on a slotted class
with self.assertRaises(
FrozenInstanceError
): # would be TypeError on a slotted class
e1.event_tuple = (1, 2, 3)
with self.assertRaises(FrozenInstanceError): # would be TypeError on a slotted class
with self.assertRaises(
FrozenInstanceError
): # would be TypeError on a slotted class
e1.type_and_code = (1, 2)
with self.assertRaises(FrozenInstanceError):

Loading…
Cancel
Save