fly-stick 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. fly_stick-0.1.0/.github/workflows/release.yml +110 -0
  2. fly_stick-0.1.0/.gitignore +21 -0
  3. fly_stick-0.1.0/.python-version +1 -0
  4. fly_stick-0.1.0/CLAUDE.md +100 -0
  5. fly_stick-0.1.0/Cargo.lock +865 -0
  6. fly_stick-0.1.0/Cargo.toml +40 -0
  7. fly_stick-0.1.0/LICENSE +21 -0
  8. fly_stick-0.1.0/PKG-INFO +336 -0
  9. fly_stick-0.1.0/README.md +324 -0
  10. fly_stick-0.1.0/devices/Microsoft X-Box 360/pad.toml +73 -0
  11. fly_stick-0.1.0/devices/Microsoft X-Box 360/series_sx.toml +87 -0
  12. fly_stick-0.1.0/devices/Thrustmaster/t16000m.toml +92 -0
  13. fly_stick-0.1.0/devices/Thrustmaster/ta320.toml +96 -0
  14. fly_stick-0.1.0/devices/Thrustmaster/tca_qeng.toml +53 -0
  15. fly_stick-0.1.0/devices/Thrustmaster/twcs.toml +85 -0
  16. fly_stick-0.1.0/devices/Thrustmaster/twcs_with_tfrp.toml +103 -0
  17. fly_stick-0.1.0/examples/alias.py +41 -0
  18. fly_stick-0.1.0/examples/btn_mode.py +42 -0
  19. fly_stick-0.1.0/examples/device_pool.py +39 -0
  20. fly_stick-0.1.0/examples/device_pool_block.py +39 -0
  21. fly_stick-0.1.0/examples/multi_device.py +152 -0
  22. fly_stick-0.1.0/examples/single_device.py +87 -0
  23. fly_stick-0.1.0/figures/Thrustmaster T.16000M.drawio +184 -0
  24. fly_stick-0.1.0/figures/Thrustmaster T.16000M.drawio.png +0 -0
  25. fly_stick-0.1.0/figures/Thrustmaster T.Flight Rudder Pedals.drawio +55 -0
  26. fly_stick-0.1.0/figures/Thrustmaster T.Flight Rudder Pedals.drawio.png +0 -0
  27. fly_stick-0.1.0/figures/Thrustmaster TCA Q-Eng 1&2.drawio +124 -0
  28. fly_stick-0.1.0/figures/Thrustmaster TCA Q-Eng 1&2.drawio.png +0 -0
  29. fly_stick-0.1.0/figures/Thrustmaster_TA320_Copilot.drawio +196 -0
  30. fly_stick-0.1.0/figures/Thrustmaster_TA320_Copilot.drawio.png +0 -0
  31. fly_stick-0.1.0/figures/Thrustmaster_TWCS_Throttle.drawio +220 -0
  32. fly_stick-0.1.0/figures/Thrustmaster_TWCS_Throttle.drawio.png +0 -0
  33. fly_stick-0.1.0/pyproject.toml +32 -0
  34. fly_stick-0.1.0/src/fly_stick/__init__.py +22 -0
  35. fly_stick-0.1.0/src/fly_stick/_core.pyi +299 -0
  36. fly_stick-0.1.0/src/inner/description.rs +409 -0
  37. fly_stick-0.1.0/src/inner/device_pool.rs +540 -0
  38. fly_stick-0.1.0/src/inner/joystick.rs +166 -0
  39. fly_stick-0.1.0/src/inner/mod.rs +3 -0
  40. fly_stick-0.1.0/src/lib.rs +23 -0
  41. fly_stick-0.1.0/src/utils.rs +312 -0
  42. fly_stick-0.1.0/src/wrapper/device_pool_wrapper.rs +130 -0
  43. fly_stick-0.1.0/src/wrapper/joystick_wrapper.rs +27 -0
  44. fly_stick-0.1.0/src/wrapper/mod.rs +2 -0
  45. fly_stick-0.1.0/uv.lock +207 -0
@@ -0,0 +1,110 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ build-wheels:
13
+ name: Build Linux wheels
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ target: [x86_64, aarch64]
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - uses: astral-sh/setup-uv@v5
22
+ with:
23
+ version: "latest"
24
+
25
+ - name: Install Python
26
+ run: uv python install 3.12
27
+
28
+ - name: Install dependencies
29
+ run: uv sync
30
+
31
+ - name: Build wheels
32
+ uses: PyO3/maturin-action@v1
33
+ with:
34
+ target: ${{ matrix.target }}
35
+ manylinux: auto
36
+ args: --release --out dist
37
+ sccache: "true"
38
+
39
+ - name: Upload wheels
40
+ uses: actions/upload-artifact@v4
41
+ with:
42
+ name: wheels-${{ matrix.target }}
43
+ path: dist/*.whl
44
+
45
+ build-sdist:
46
+ name: Build source distribution
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+
51
+ - uses: astral-sh/setup-uv@v5
52
+ with:
53
+ version: "latest"
54
+
55
+ - name: Install Python
56
+ run: uv python install 3.12
57
+
58
+ - name: Install dependencies
59
+ run: uv sync
60
+
61
+ - name: Build sdist
62
+ uses: PyO3/maturin-action@v1
63
+ with:
64
+ command: sdist
65
+ args: --out dist
66
+
67
+ - name: Upload sdist
68
+ uses: actions/upload-artifact@v4
69
+ with:
70
+ name: sdist
71
+ path: dist/*.tar.gz
72
+
73
+ publish-pypi:
74
+ name: Publish to PyPI
75
+ runs-on: ubuntu-latest
76
+ needs: [build-wheels, build-sdist]
77
+ environment:
78
+ name: pypi
79
+ url: https://pypi.org/p/fly-stick
80
+ permissions:
81
+ id-token: write
82
+ steps:
83
+ - name: Download all artifacts
84
+ uses: actions/download-artifact@v4
85
+ with:
86
+ path: dist
87
+ merge-multiple: true
88
+
89
+ - name: Publish to PyPI
90
+ uses: PyO3/maturin-action@v1
91
+ with:
92
+ command: upload
93
+ args: --non-interactive --skip-existing dist/*
94
+
95
+ github-release:
96
+ name: Create GitHub Release
97
+ runs-on: ubuntu-latest
98
+ needs: [build-wheels, build-sdist]
99
+ steps:
100
+ - name: Download all artifacts
101
+ uses: actions/download-artifact@v4
102
+ with:
103
+ path: dist
104
+ merge-multiple: true
105
+
106
+ - name: Create Release
107
+ uses: softprops/action-gh-release@v2
108
+ with:
109
+ files: dist/*
110
+ generate_release_notes: true
@@ -0,0 +1,21 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ target/
13
+
14
+ *.so
15
+ *.dll
16
+ *.dylib
17
+ *.pyd
18
+
19
+ *.bkp
20
+
21
+ IMG_*
@@ -0,0 +1 @@
1
+ 3.10
@@ -0,0 +1,100 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project overview
6
+
7
+ `fly_stick` is a **Linux-only** Python extension built with Rust and PyO3. It reads game-controller input via the Linux `evdev` subsystem and exposes `PyJoystick`, `PyDevicePool`, and descriptor types to Python. The Rust crate is built as a `cdylib` and PyO3 is configured with `abi3-py39`, so a single manylinux wheel covers CPython 3.9+ on Linux x86_64.
8
+
9
+ ## Build & development commands
10
+
11
+ All commands assume the working directory is the repository root (`toolkit/fly_stick/`).
12
+
13
+ Install Python dependencies:
14
+
15
+ ```bash
16
+ uv sync
17
+ ```
18
+
19
+ Build and install the extension into the active virtualenv for local development:
20
+
21
+ ```bash
22
+ uv run maturin develop
23
+ ```
24
+
25
+ Run Rust tests:
26
+
27
+ ```bash
28
+ cargo test
29
+ ```
30
+
31
+ Run Python tests:
32
+
33
+ ```bash
34
+ uv run pytest
35
+ ```
36
+
37
+ Build a release wheel:
38
+
39
+ ```bash
40
+ uv run maturin build --release
41
+ ```
42
+
43
+ Format and lint Rust:
44
+
45
+ ```bash
46
+ cargo fmt
47
+ cargo clippy
48
+ ```
49
+
50
+ Python linting is not currently configured. Add a ruff/mypy setup only if you introduce non-trivial Python logic beyond `src/fly_stick/__init__.py`.
51
+
52
+ ## Running a single test
53
+
54
+ Rust single test:
55
+
56
+ ```bash
57
+ cargo test <test_name>
58
+ ```
59
+
60
+ Python single test:
61
+
62
+ ```bash
63
+ uv run pytest tests/test_<name>.py -v
64
+ ```
65
+
66
+ ## Architecture
67
+
68
+ ### Extension boundary
69
+
70
+ `src/lib.rs` defines the PyO3 `_core` extension module. It is gated with `#[cfg(target_os = "linux")]` because the only backend uses `evdev`. On non-Linux builds the module symbol is absent and the crate will not produce a usable Python extension.
71
+
72
+ ### Rust layers
73
+
74
+ - `src/inner/` — core logic with no direct PyO3 dependency.
75
+ - `description.rs` — `DeviceDescription` and `DeviceItem` parsed from TOML; defines expected axes/buttons/hats and builds default `JoystickState`.
76
+ - `joystick.rs` — opens a single `/dev/input/event*` device via `evdev::Device`, normalizes ABS axis values, and reads events into `JoystickState`.
77
+ - `device_pool.rs` — manages multiple logical devices, spawns async Tokio tasks per device to update a shared input register, supports `fetch()` (await change/timeout) and `fetch_nowait()`, plus debouncing and trigger/hold button modes.
78
+ - `src/utils.rs` — cross-cutting types exposed to Python: `JoystickInfo`, `JoystickState`, `DeviceButtonMode`, plus `fetch_connected_joysticks()` wrapping `evdev::enumerate()`.
79
+ - `src/wrapper/` — thin PyO3 wrappers around the inner types.
80
+ - `joystick_wrapper.rs` — `PyJoystick`.
81
+ - `device_pool_wrapper.rs` — `PyDevicePool`; its async methods are exposed as Rust `async fn` and can be awaited from Python asyncio.
82
+
83
+ ### Python side
84
+
85
+ - `src/fly_stick/__init__.py` re-exports all public symbols from `fly_stick._core`.
86
+ - `src/fly_stick/_core.pyi` provides the type stubs.
87
+
88
+ ### Concurrency model
89
+
90
+ `DevicePool` uses Tokio via `pyo3-async-runtimes`. Each monitored device gets a Tokio task that reads `evdev` events and updates a shared input register protected by `std::sync::Mutex`. `stop()` or `reset()` sends a shutdown signal through an `mpsc` channel to abort those tasks.
91
+
92
+ ### Device descriptions
93
+
94
+ Devices are configured with TOML files under `devices/`. `DeviceDescription.from_toml(path)` is exposed to Python and expects the file format shown in `README.md`. Example files and button-mapping diagrams live in `examples/` and `figures/`.
95
+
96
+ ### Platform constraints
97
+
98
+ - Only Linux is supported.
99
+ - Do not add Windows/macOS-specific API calls without also adding a corresponding platform backend; `evdev` itself is Linux-only.
100
+ - When modifying `Cargo.toml`, keep `evdev` under a Linux-only dependency section or gate usages with `#[cfg(target_os = "linux")]`.