Skip to content

Commit 6ef2f15

Browse files
authored
Merge pull request #4 from Geson-anko/feature/inherits-virtual-device
Inherits Virtual Device class in python bindings
2 parents da03d66 + 16b03a9 commit 6ef2f15

File tree

9 files changed

+63
-68
lines changed

9 files changed

+63
-68
lines changed

bindings/python/src/inputtino/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from importlib import metadata
22

3-
from .base import DeviceDefinition
3+
from .base import DeviceDefinition, VirtualDevice
44
from .joypad import (
55
ControllerButton,
66
Joypad,
@@ -39,4 +39,5 @@
3939
"PenButtonType",
4040
"PenTablet",
4141
"PenToolType",
42+
"VirtualDevice",
4243
]

bindings/python/src/inputtino/base.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,24 @@ def to_core(self) -> _core.DeviceDefinition:
4040
definition.device_phys = self.device_phys
4141
definition.device_uniq = self.device_uniq
4242
return definition
43+
44+
45+
class VirtualDevice:
46+
"""Base class for all virtual input devices."""
47+
48+
def __init__(self, device: _core.VirtualDevice) -> None:
49+
"""Initialize virtual device.
50+
51+
Args:
52+
device: Core virtual device instance
53+
"""
54+
self._device = device
55+
56+
@property
57+
def nodes(self) -> list[str]:
58+
"""Get the device nodes created by this virtual device.
59+
60+
Returns:
61+
List of device node paths representing the virtual device in /dev/input/
62+
"""
63+
return self._device.get_nodes()

bindings/python/src/inputtino/joypad.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
PS5MotionType,
1111
StickPosition,
1212
)
13-
from .base import DeviceDefinition
13+
from .base import DeviceDefinition, VirtualDevice
1414

1515

1616
class ControllerButton(IntFlag):
@@ -44,7 +44,7 @@ class ControllerButton(IntFlag):
4444
Y = CoreButton.Y.value
4545

4646

47-
class Joypad:
47+
class Joypad(VirtualDevice):
4848
"""Base class for all joypad implementations."""
4949

5050
def __init__(self, device_def: DeviceDefinition, joypad: _core.Joypad) -> None:
@@ -54,18 +54,10 @@ def __init__(self, device_def: DeviceDefinition, joypad: _core.Joypad) -> None:
5454
device_def: Device definition for the joypad
5555
joypad: Core joypad instance
5656
"""
57+
super().__init__(joypad)
5758
self._device_def = device_def
5859
self._joypad = joypad
5960

60-
@property
61-
def nodes(self) -> list[str]:
62-
"""Get device nodes created by this virtual joypad.
63-
64-
Returns:
65-
List of device node paths
66-
"""
67-
return self._joypad.get_nodes()
68-
6961
def set_pressed_buttons(self, buttons: ControllerButton) -> None:
7062
"""Set currently pressed buttons.
7163

bindings/python/src/inputtino/keyboard.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from typing_extensions import Self
99

1010
from . import _core
11-
from .base import DeviceDefinition
11+
from .base import DeviceDefinition, VirtualDevice
1212

1313
# Default device definition for keyboard
1414
DEFAULT_KEYBOARD = DeviceDefinition(
@@ -19,7 +19,7 @@
1919
)
2020

2121

22-
class Keyboard:
22+
class Keyboard(VirtualDevice):
2323
"""Virtual keyboard input device.
2424
2525
This class provides functionality to simulate keyboard input.
@@ -51,6 +51,7 @@ def __init__(
5151
RuntimeError: If device creation fails
5252
"""
5353
self._keyboard = _core.Keyboard.create(device_def.to_core(), millis_repress_key)
54+
super().__init__(self._keyboard)
5455

5556
def press(self, key_code: int) -> None:
5657
"""Press a keyboard key.
@@ -68,15 +69,6 @@ def release(self, key_code: int) -> None:
6869
"""
6970
self._keyboard.release(key_code)
7071

71-
@property
72-
def nodes(self) -> list[str]:
73-
"""Get the device nodes created by this virtual keyboard.
74-
75-
Returns:
76-
List of device node paths
77-
"""
78-
return self._keyboard.get_nodes()
79-
8072
def type(self, key_code: int, duration: float = 0.1) -> None:
8173
"""Press and release a key with specified duration.
8274

bindings/python/src/inputtino/mouse.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from . import _core
66
from ._core import MouseButton
7-
from .base import DeviceDefinition
7+
from .base import DeviceDefinition, VirtualDevice
88

99
# Default device definition for mouse
1010
DEFAULT_MOUSE = DeviceDefinition(
@@ -15,7 +15,7 @@
1515
)
1616

1717

18-
class Mouse:
18+
class Mouse(VirtualDevice):
1919
"""Virtual mouse input device.
2020
2121
This class provides functionality to simulate mouse movements,
@@ -33,6 +33,7 @@ def __init__(self, device_def: DeviceDefinition = DEFAULT_MOUSE) -> None:
3333
RuntimeError: If device creation fails
3434
"""
3535
self._mouse = _core.Mouse.create(device_def.to_core())
36+
super().__init__(self._mouse)
3637

3738
def move(self, delta_x: int, delta_y: int) -> None:
3839
"""Move the mouse cursor relative to its current position.
@@ -88,15 +89,6 @@ def scroll_horizontal(self, distance: int) -> None:
8889
"""
8990
self._mouse.horizontal_scroll(distance)
9091

91-
@property
92-
def nodes(self) -> list[str]:
93-
"""Get the device nodes created by this virtual mouse.
94-
95-
Returns:
96-
List of device node paths
97-
"""
98-
return self._mouse.get_nodes()
99-
10092
def click(
10193
self, button: MouseButton = MouseButton.LEFT, duration: float = 0.0
10294
) -> None:

bindings/python/src/inputtino/pentablet.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from . import _core
44
from ._core import PenButtonType, PenToolType
5-
from .base import DeviceDefinition
5+
from .base import DeviceDefinition, VirtualDevice
66

77
# Default device definition for pen tablet
88
DEFAULT_PEN_TABLET = DeviceDefinition(
@@ -13,7 +13,7 @@
1313
)
1414

1515

16-
class PenTablet:
16+
class PenTablet(VirtualDevice):
1717
"""Virtual pen tablet input device.
1818
1919
This class provides functionality to simulate pen tablet input with
@@ -35,6 +35,7 @@ def __init__(self, device_def: DeviceDefinition = DEFAULT_PEN_TABLET) -> None:
3535
RuntimeError: If device creation fails
3636
"""
3737
self._tablet = _core.PenTablet.create(device_def.to_core())
38+
super().__init__(self._tablet)
3839

3940
def place_tool(
4041
self,
@@ -70,12 +71,3 @@ def set_button(self, button: PenButtonType, pressed: bool) -> None:
7071
pressed: True if button is pressed, False if released
7172
"""
7273
self._tablet.set_btn(button, pressed)
73-
74-
@property
75-
def nodes(self) -> list[str]:
76-
"""Get the device nodes created by this virtual pen tablet.
77-
78-
Returns:
79-
List of device node paths
80-
"""
81-
return self._tablet.get_nodes()

bindings/python/src/inputtino/touchscreen.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Touchscreen input device implementation."""
22

33
from . import _core
4-
from .base import DeviceDefinition
4+
from .base import DeviceDefinition, VirtualDevice
55

66
# Default device definition for touchscreen
77
DEFAULT_TOUCHSCREEN = DeviceDefinition(
@@ -12,7 +12,7 @@
1212
)
1313

1414

15-
class TouchScreen:
15+
class TouchScreen(VirtualDevice):
1616
"""Virtual touchscreen input device.
1717
1818
This class provides functionality to simulate touchscreen
@@ -31,6 +31,7 @@ def __init__(self, device_def: DeviceDefinition = DEFAULT_TOUCHSCREEN) -> None:
3131
RuntimeError: If device creation fails
3232
"""
3333
self._touchscreen = _core.TouchScreen.create(device_def.to_core())
34+
super().__init__(self._touchscreen)
3435

3536
def place_finger(
3637
self,
@@ -58,12 +59,3 @@ def release_finger(self, finger_nr: int) -> None:
5859
finger_nr: Finger number to release
5960
"""
6061
self._touchscreen.release_finger(finger_nr)
61-
62-
@property
63-
def nodes(self) -> list[str]:
64-
"""Get the device nodes created by this virtual touchscreen.
65-
66-
Returns:
67-
List of device node paths
68-
"""
69-
return self._touchscreen.get_nodes()

bindings/python/src/inputtino/trackpad.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Trackpad input device implementation."""
22

33
from . import _core
4-
from .base import DeviceDefinition
4+
from .base import DeviceDefinition, VirtualDevice
55

66
DEFAULT_TRACKPAD = DeviceDefinition(
77
name="Wolf (virtual) touchpad",
@@ -11,7 +11,7 @@
1111
)
1212

1313

14-
class Trackpad:
14+
class Trackpad(VirtualDevice):
1515
"""Virtual trackpad input device.
1616
1717
This class provides functionality to simulate multi-touch trackpad
@@ -33,6 +33,7 @@ def __init__(self, device_def: DeviceDefinition = DEFAULT_TRACKPAD) -> None:
3333
RuntimeError: If device creation fails
3434
"""
3535
self._trackpad = _core.Trackpad.create(device_def.to_core())
36+
super().__init__(self._trackpad)
3637

3738
def place_finger(
3839
self,
@@ -71,12 +72,3 @@ def set_left_button(self, pressed: bool) -> None:
7172
pressed: True to press the button, False to release
7273
"""
7374
self._trackpad.set_left_btn(pressed)
74-
75-
@property
76-
def nodes(self) -> list[str]:
77-
"""Get the device nodes created by this virtual trackpad.
78-
79-
Returns:
80-
List of device node paths
81-
"""
82-
return self._trackpad.get_nodes()

bindings/python/tests/test_base.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
from unittest.mock import MagicMock
2+
3+
import pytest
4+
15
from inputtino import _core
2-
from inputtino.base import DeviceDefinition
6+
from inputtino.base import DeviceDefinition, VirtualDevice
37

48

59
def test_device_definition_creation():
@@ -37,3 +41,20 @@ def test_device_definition_to_core():
3741
assert core_def.version == definition.version
3842
assert core_def.device_phys == definition.device_phys
3943
assert core_def.device_uniq == definition.device_uniq
44+
45+
46+
@pytest.fixture
47+
def mock_core_device():
48+
"""Create a mock for core VirtualDevice."""
49+
mock_device = MagicMock(spec=_core.VirtualDevice)
50+
mock_device.get_nodes.return_value = ["/dev/input/event0", "/dev/input/mouse0"]
51+
return mock_device
52+
53+
54+
def test_virtual_device_nodes(mock_core_device):
55+
"""Test getting device nodes from virtual device."""
56+
device = VirtualDevice(mock_core_device)
57+
nodes = device.nodes
58+
59+
assert nodes == ["/dev/input/event0", "/dev/input/mouse0"]
60+
mock_core_device.get_nodes.assert_called_once()

0 commit comments

Comments
 (0)