refactor: modernize the project layout and tooling - #4
Merged
WigoWigo10 merged 7 commits intoAug 1, 2026
Merged
Conversation
With the package at the repository root, `import directkeys` from the checkout directory picks up the source tree rather than the installed distribution. That hides packaging mistakes: a module missing from the wheel still imports fine locally and only fails for users. Moving to src/ makes the test run exercise the installed package. Also folds .coveragerc into pyproject.toml and configures pytest there, so `testpaths` and the tests/manual exclusion no longer have to be repeated on every invocation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Python 3.8 reached end of life in October 2024 and no longer receives security fixes, so requires-python moves to 3.9 and the CI matrix follows (3.9, 3.11, 3.13 on Windows and Linux). This also removes the need to pin an older Ubuntu runner, since 3.8 is the version ubuntu-latest stopped shipping. With Python 2 long out of scope, the compatibility layer was dead weight that made every module harder to read: - Remove the `basestring` / `unichr` / `long` fallbacks and the `from __future__` imports, using `str`, `chr` and `int` directly. - Remove the `time.monotonic` fallback, present on every supported version. - Replace the Python2 `Queue` / `threading._Event` branch with a plain import. - Turn the `_is_str` / `_is_number` / `_is_list` lambdas into functions and drop the redundant `(object)` base classes and UTF-8 coding cookies. - Restore two upstream comments explaining `_State` and the `_Event.wait` override, lost when the compatibility block was edited. Also introduces `__version__` as the canonical attribute, keeping `version` as an alias so code reading `keyboard.version` keeps working. The setuptools dynamic version now points at `__version__`, which is a literal and can be read statically; the alias is not, and would have forced an import at build time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds Ruff (lint + import sorting) configured in pyproject.toml, targeting py39. Rules that the codebase deliberately breaks are ignored explicitly, each with the reason, rather than left to fail: long lines in the ctypes tables, imports that must follow the platform dispatch, and the Cyrillic/Greek key names in _canonical_names.py that RUF001 reads as ambiguous characters. The autofixable findings are applied. Two are worth calling out: - tests/test_keyboard.py defined four tests twice under the same name, so the first definition of each was silently discarded and never ran. They are not duplicates, they are distinct cases: a `write` without delay, a hotkey removal without modifiers, a two-modifier release, and a multistep blocking state assertion. Renamed so both run; the suite goes from 157 to 161 tests and all four recovered cases pass. - `index = 0` in the suppression path assigned to a local that nothing read, right before `set_index(0)` did the real work. A group of upstream findings is ignored rather than fixed, because each would change runtime behaviour and none is covered by a test: repeated dictionary keys (F601), mutable argument defaults (B006), bare except (E722) and `raise` without `from` (B904). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Mechanical reformat of every Python file, in its own commit so the substantive changes elsewhere stay reviewable. Two settings needed care: - `docstring-code-format` is left off. The __init__ docstring is published verbatim as the PyPI description and regenerated into README.md, so the formatter must not rewrite the example code inside it. - Markdown is excluded. Ruff reformats fenced Python blocks in .md files, and since README.md is generated from that same docstring, the formatter and the generator would each keep undoing the other. Verified by comparing the AST of every touched file before and after: 17 are byte-identical, and the remaining 8 differ only in whitespace inside string literals, where Ruff normalises `""" Text. """` to `"""Text."""`. No structural change in any file. README.md is regenerated so it stays in sync with the docstring after that normalisation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rounds out the tooling so the checks that CI runs can also run locally before a commit, and so contributors get consistent whitespace regardless of editor. - .pre-commit-config.yaml runs Ruff (check + format) plus the standard whitespace and syntax hooks. README.md is excluded from the whitespace hooks because it is generated from the module docstring. - The `mixed-line-ending` hook is deliberately left out: `.gitattributes` already normalises endings at the git level, and forcing LF in the working tree would fight the CRLF checkout on Windows in a loop. - .editorconfig mirrors the same rules for editors. - Dependabot keeps the Actions and pip pins current, monthly. - A `lint` job runs Ruff in CI. .gitattributes drops the Visual Studio and msysgit boilerplate inherited from the original template, keeps the `text=auto` normalisation, and marks README.md as generated so it stops inflating pull request diffs. Verified by running `pre-commit run --all-files` twice: the second run is clean, so the hooks are idempotent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Records the modernisation in CHANGES.md, including the Python 3.9 requirement, the src/ layout and the tooling, alongside the fixes made earlier on the fork. The module docstring gains a Development section covering the editable install, pre-commit and the two Ruff checks CI runs, and states the supported Python version where the removed "Python 2 and 3" line used to be. README.md is regenerated from it. Also widens the margin in test_record. The test races a background thread that has to register both the recording hook and the suppressing hotkey before the events are fed in, and upstream already noted the 0.01s sleep had lost that race once; it lost it again here. There is no public barrier to synchronise on, so this is a larger margin rather than a real fix, and the comment says so. Ten consecutive full runs pass afterwards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.