diff options
author | CoprDistGit <infra@openeuler.org> | 2023-05-18 06:22:16 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2023-05-18 06:22:16 +0000 |
commit | 84e6d8f7ca9147dc3051c730cb2d2e396568c2e5 (patch) | |
tree | 8a6a97d7759e86725ab89ee428b9ec0dff671776 | |
parent | 7cf2a289463bdb0b3e3f4b2a34ae6946ac4c8936 (diff) |
automatic import of python-sshkeyboard
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | python-sshkeyboard.spec | 1326 | ||||
-rw-r--r-- | sources | 1 |
3 files changed, 1328 insertions, 0 deletions
@@ -0,0 +1 @@ +/sshkeyboard-2.3.1.tar.gz diff --git a/python-sshkeyboard.spec b/python-sshkeyboard.spec new file mode 100644 index 0000000..c86688a --- /dev/null +++ b/python-sshkeyboard.spec @@ -0,0 +1,1326 @@ +%global _empty_manifest_terminate_build 0 +Name: python-sshkeyboard +Version: 2.3.1 +Release: 1 +Summary: sshkeyboard +License: MIT License +URL: https://pypi.org/project/sshkeyboard/ +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/e3/7b/d78e6ade4bb4680d0a610ed02047c4de04db62de8864193bf842c59c47cb/sshkeyboard-2.3.1.tar.gz +BuildArch: noarch + + +%description +# sshkeyboard + +The only keyboard event callback library that works _everywhere_, even when +used through an [SSH](https://en.wikipedia.org/wiki/Secure_Shell) connection +(hence the name). + +It works with headless computers and servers, or for example inside Windows +Subsystem for Linux (WSL 2). One good use case is controlling Raspberry Pi +based robots or RC cars through SSH. Note that this library can also be used +locally without an SSH connection. + +It does not depend on X server, uinput, root access (sudo) or +any external dependencies. + +Supports [asyncio](https://docs.python.org/3/library/asyncio.html) and +sequential/concurrent callback modes. For Python 3.6+. + +[Documentation](https://sshkeyboard.readthedocs.io) - +[Github source](https://github.com/ollipal/sshkeyboard) - +[PyPI](https://pypi.org/project/sshkeyboard/) - +[Reference](https://sshkeyboard.readthedocs.io/en/latest/reference.html) - +[](https://pepy.tech/project/sshkeyboard) + +## Quick start + +Installation: + +```text +pip install sshkeyboard +``` + +Simple example to fire events when a key is pressed or released. +`esc` key ends listening by default: + +```python +from sshkeyboard import listen_keyboard + +def press(key): + print(f"'{key}' pressed") + +def release(key): + print(f"'{key}' released") + +listen_keyboard( + on_press=press, + on_release=release, +) +``` + +Output: + +```text +$ python example.py +'a' pressed +'a' released +``` + +## How it works + +The sshkeyboard library works without +[X server](https://en.wikipedia.org/wiki/X_Window_System) +and [uinput](https://www.kernel.org/doc/html/v4.12/input/uinput.html). + +On Unix based systems (such as Linux, macOS) it works by parsing characters +from [sys.stdin](https://docs.python.org/3/library/sys.html#sys.stdin). This +is done with [fcntl](https://docs.python.org/3/library/fcntl.html) and +[termios](https://docs.python.org/3/library/termios.html) standard library +modules. + +On Windows [msvcrt](https://docs.python.org/3/library/msvcrt.html) standard +library module is used to read user input. The Windows support is still new, +so please create [an issue](https://github.com/ollipal/sshkeyboard/issues) +if you run into problems. + +This behaviour allows it to work where other libraries like +[pynput](#comparison-to-other-keyboard-libraries) or +[keyboard](#comparison-to-other-keyboard-libraries) do not work, but +it comes with some **limitations**, mainly: + +1. Holding multiple keys down at the same time does not work, the library + releases the previous keys when a new one is pressed. Releasing keys also + happens after a short delay, and some key presses can get lost if the same + key gets spammed fast. +2. Some keys do not write to `sys.stdin` when pressed, such as `Ctrl`, + `Shift`, `Caps Lock`, `Alt` and `Windows`/`Command`/`Super` key. That is + why this library does not attempt to parse those even if they could be + technically be parsed in some cases + +## Advanced use + +### Sequential mode + +Normally this library allows `on_press` and `on_release` callbacks to be run +concurrently. This means that by running: + +```python +import time +from sshkeyboard import listen_keyboard + +def press(key): + print(f"'{key}' pressed") + time.sleep(3) + print(f"'{key}' slept") + +listen_keyboard(on_press=press) +``` + +and pressing `"a"`, `"s"` and `"d"` keys will log: + +```text +'a' pressed +'s' pressed +'d' pressed +'a' slept +'s' slept +'d' slept +``` + +But sometimes you don't want to allow the callbacks to overlap, then +you should set `sequential` parameter to `True`: + +```python +# ... +listen_keyboard( + on_press=press, + sequential=True, +) +``` + +Then pressing `"a"`, `"s"` and `"d"` keys will log: + +```text +'a' pressed +'a' slept +'s' pressed +'s' slept +'d' pressed +'d' slept +``` + +### Asyncio + +You can also use asynchronous functions as `on_press` / `on_release` callbacks +with `listen_keyboard`: + +```python +import asyncio +from sshkeyboard import listen_keyboard + +async def press(key): + print(f"'{key}' pressed") + await asyncio.sleep(3) + print(f"'{key}' slept") + +listen_keyboard(on_press=press) +``` + +> **NOTE** remember to use `await asyncio.sleep(...)` in async callbacks +instead of `time.sleep(...)` or the timings will fail: + +### Mixing asynchronous and concurrent callbacks + +`listen_keyboard` also supports mixing asynchronous and concurrent callbacks: + +```python +import asyncio +import time +from sshkeyboard import listen_keyboard + +async def press(key): + print(f"'{key}' pressed") + await asyncio.sleep(3) + print(f"'{key}' press slept") + +def release(key): + print(f"'{key}' relased") + time.sleep(3) + print(f"'{key}' release slept") + +listen_keyboard( + on_press=press, + on_release=release, +) +``` + +Here pressing `"a"` and `"s"` will log: + +```text +'a' pressed +'a' relased +'s' pressed +'s' relased +'a' press slept +'s' press slept +'a' release slept +'s' release slept +``` + +And with `sequential=True`: + +```python +# ... +listen_keyboard( + on_press=press, + on_release=release, + sequential=True, +) +``` + +will log: + +```text +'a' pressed +'a' press slept +'a' relased +'a' release slept +'s' pressed +'s' press slept +'s' relased +'s' release slept +``` + +> **NOTE** remember to use `await asyncio.sleep(...)` in async callbacks +instead of `time.sleep(...)` or the timings will fail: + +### Stop listening + +You can change the key that ends the listening by giving `until` parameter, +which defaults to `"esc"`: + +```python +# ... +listen_keyboard( + on_press=press, + until="space", +) +``` + +You also can manually stop listening by calling `stop_listening()` from the +callback or from some other function: + +```python +from sshkeyboard import listen_keyboard, stop_listening + +def press(key): + print(f"'{key}' pressed") + if key == "z": + stop_listening() + +listen_keyboard(on_press=press) +``` + +`until` can be also set to `None`. This means that listening ends only with +`stop_listening()` or if an error has been raised. + +### Troubleshooting + +If some keys do not seem to register correctly, try turning the debug mode on. +This will add logs if some keys are skipped intentionally: + +```python +# ... +listen_keyboard( + on_press=press, + debug=True, +) +``` + +If one key press causes multiple `on_press` / `on_release` callbacks or if +releasing happens too slowly, you can try to tweak the default timing +parameters: + +```python +# ... +listen_keyboard( + on_press=press, + delay_second_char=0.75, + delay_other_chars=0.05, +) +``` + +### More + +Check out the full +[reference](https://sshkeyboard.readthedocs.io/en/latest/reference.html) +for more functions and parameters such as: + +- `lower` parameter +- `sleep` parameter +- `max_thread_pool_workers` parameter +- `listen_keyboard_manual` function + +Direct links to functions: + +- [listen_keyboard](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.listen_keyboard) +- [stop_listening](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.stop_listening) +- [listen_keyboard_manual](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.listen_keyboard_manual) + +## Development + +This sections explains how to build the documentation and how to run the +[pre-commit script](https://github.com/ollipal/sshkeyboard/blob/main/pre-commit) +locally. This helps if you want to create +[a pull request](https://github.com/ollipal/sshkeyboard/pulls) +or if you just want to try things out. + +Building the documentations allows you to build all of the files served on the +[documentation](https://sshkeyboard.readthedocs.io) site locally. + +The +[pre-commit script](https://github.com/ollipal/sshkeyboard/blob/main/pre-commit) +handles running tests, formatting and +linting before each Git commit. These same checks also run automatically on +[Github Actions](https://github.com/ollipal/sshkeyboard/blob/main/.github/workflows/main.yml). + +Start by cloning this library, and change directory to the project root: + +```text +git clone git@github.com:ollipal/sshkeyboard.git +cd sshkeyboard +``` + +Optionally, create and activate a virtual environment at the root of the +project (you might need to use `python3` keyword instead of `python`): + +```text +python -m venv .env +source .env/bin/activate +``` + +(Later you can deactivate the virtual environment with: `deactivate`) + +To build the documentation or run the pre-commit script locally, you need +to install the development dependencies: + +```text +pip install -r dev-requirements.txt +``` + +### Documentation + +To build the documentation locally, first change into `docs/` directory: + +```text +cd docs +``` + +Then to build the documentation, call: + +```text +make html +``` + +Now you should have a new `docs/build/` directory, and you can open +`<your-clone-path>/sshkeyboard/docs/build/html/index.html` from your browser. + +You can force the rebuild by running: + +```text +rm -rf build/ && make html +``` + +You can change the documentation content by changing `README.md` or files from +`src/` or `docs/source/`. If you are mainly changing contents from +`docs/source/`, you can enable automatic re-building by running: + +```text +sphinx-autobuild ./source/ ./build/html/ +``` + +### Running the pre-commit script + +You can run the **tests** +([tox](https://tox.wiki/en/latest/index.html), +[pytest](https://docs.pytest.org)), **formatting** +([black](https://black.readthedocs.io/en/stable/), +[isort](https://pycqa.github.io/isort/)) and **linting** +([pflake8](https://github.com/csachs/pyproject-flake8), +[pep8-naming](https://github.com/PyCQA/pep8-naming), +[codespell](https://github.com/codespell-project/codespell), +[markdownlint](https://github.com/markdownlint/markdownlint)) simply by +executing: + +```text +./pre-commit +``` + +Now if you want to automatically run these when you call `git commit`, copy +the script into `.git/hooks/` directory: + +```text +cp pre-commit .git/hooks +``` + +> **NOTE**: this process does not run `markdownlint` by default as it +requires [Ruby](https://www.ruby-lang.org/en/) to be installed. If you want +to run `markdownlint` locally as well, +[install Ruby](https://www.ruby-lang.org/en/documentation/installation/) +and install markdown lint with `gem install mdl -v 0.11.0`. Then from +`pre-commit` change `RUN_MDL=false` to `RUN_MDL=true`. (You need to copy the +file again into `.git/hooks/` if you did that earlier) + +## Comparison to other keyboard libraries + +The other keyboard libraries work by reading proper keycodes from the system. + +This means that they usually require either +[X server](https://en.wikipedia.org/wiki/X_Window_System) or +[uinput](https://www.kernel.org/doc/html/v4.12/input/uinput.html), so they do +not work over SSH. But this means they do not have the same +[limitations](#how-it-works) as this library. + +They usually can also support more features such as pressing the keys instead +of just reacting to user input. + +I have good experiences from these libraries: + +- [pynput](https://pynput.readthedocs.io/en/latest/) +- [keyboard](https://github.com/boppreh/keyboard) (requires sudo) + +%package -n python3-sshkeyboard +Summary: sshkeyboard +Provides: python-sshkeyboard +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-sshkeyboard +# sshkeyboard + +The only keyboard event callback library that works _everywhere_, even when +used through an [SSH](https://en.wikipedia.org/wiki/Secure_Shell) connection +(hence the name). + +It works with headless computers and servers, or for example inside Windows +Subsystem for Linux (WSL 2). One good use case is controlling Raspberry Pi +based robots or RC cars through SSH. Note that this library can also be used +locally without an SSH connection. + +It does not depend on X server, uinput, root access (sudo) or +any external dependencies. + +Supports [asyncio](https://docs.python.org/3/library/asyncio.html) and +sequential/concurrent callback modes. For Python 3.6+. + +[Documentation](https://sshkeyboard.readthedocs.io) - +[Github source](https://github.com/ollipal/sshkeyboard) - +[PyPI](https://pypi.org/project/sshkeyboard/) - +[Reference](https://sshkeyboard.readthedocs.io/en/latest/reference.html) - +[](https://pepy.tech/project/sshkeyboard) + +## Quick start + +Installation: + +```text +pip install sshkeyboard +``` + +Simple example to fire events when a key is pressed or released. +`esc` key ends listening by default: + +```python +from sshkeyboard import listen_keyboard + +def press(key): + print(f"'{key}' pressed") + +def release(key): + print(f"'{key}' released") + +listen_keyboard( + on_press=press, + on_release=release, +) +``` + +Output: + +```text +$ python example.py +'a' pressed +'a' released +``` + +## How it works + +The sshkeyboard library works without +[X server](https://en.wikipedia.org/wiki/X_Window_System) +and [uinput](https://www.kernel.org/doc/html/v4.12/input/uinput.html). + +On Unix based systems (such as Linux, macOS) it works by parsing characters +from [sys.stdin](https://docs.python.org/3/library/sys.html#sys.stdin). This +is done with [fcntl](https://docs.python.org/3/library/fcntl.html) and +[termios](https://docs.python.org/3/library/termios.html) standard library +modules. + +On Windows [msvcrt](https://docs.python.org/3/library/msvcrt.html) standard +library module is used to read user input. The Windows support is still new, +so please create [an issue](https://github.com/ollipal/sshkeyboard/issues) +if you run into problems. + +This behaviour allows it to work where other libraries like +[pynput](#comparison-to-other-keyboard-libraries) or +[keyboard](#comparison-to-other-keyboard-libraries) do not work, but +it comes with some **limitations**, mainly: + +1. Holding multiple keys down at the same time does not work, the library + releases the previous keys when a new one is pressed. Releasing keys also + happens after a short delay, and some key presses can get lost if the same + key gets spammed fast. +2. Some keys do not write to `sys.stdin` when pressed, such as `Ctrl`, + `Shift`, `Caps Lock`, `Alt` and `Windows`/`Command`/`Super` key. That is + why this library does not attempt to parse those even if they could be + technically be parsed in some cases + +## Advanced use + +### Sequential mode + +Normally this library allows `on_press` and `on_release` callbacks to be run +concurrently. This means that by running: + +```python +import time +from sshkeyboard import listen_keyboard + +def press(key): + print(f"'{key}' pressed") + time.sleep(3) + print(f"'{key}' slept") + +listen_keyboard(on_press=press) +``` + +and pressing `"a"`, `"s"` and `"d"` keys will log: + +```text +'a' pressed +'s' pressed +'d' pressed +'a' slept +'s' slept +'d' slept +``` + +But sometimes you don't want to allow the callbacks to overlap, then +you should set `sequential` parameter to `True`: + +```python +# ... +listen_keyboard( + on_press=press, + sequential=True, +) +``` + +Then pressing `"a"`, `"s"` and `"d"` keys will log: + +```text +'a' pressed +'a' slept +'s' pressed +'s' slept +'d' pressed +'d' slept +``` + +### Asyncio + +You can also use asynchronous functions as `on_press` / `on_release` callbacks +with `listen_keyboard`: + +```python +import asyncio +from sshkeyboard import listen_keyboard + +async def press(key): + print(f"'{key}' pressed") + await asyncio.sleep(3) + print(f"'{key}' slept") + +listen_keyboard(on_press=press) +``` + +> **NOTE** remember to use `await asyncio.sleep(...)` in async callbacks +instead of `time.sleep(...)` or the timings will fail: + +### Mixing asynchronous and concurrent callbacks + +`listen_keyboard` also supports mixing asynchronous and concurrent callbacks: + +```python +import asyncio +import time +from sshkeyboard import listen_keyboard + +async def press(key): + print(f"'{key}' pressed") + await asyncio.sleep(3) + print(f"'{key}' press slept") + +def release(key): + print(f"'{key}' relased") + time.sleep(3) + print(f"'{key}' release slept") + +listen_keyboard( + on_press=press, + on_release=release, +) +``` + +Here pressing `"a"` and `"s"` will log: + +```text +'a' pressed +'a' relased +'s' pressed +'s' relased +'a' press slept +'s' press slept +'a' release slept +'s' release slept +``` + +And with `sequential=True`: + +```python +# ... +listen_keyboard( + on_press=press, + on_release=release, + sequential=True, +) +``` + +will log: + +```text +'a' pressed +'a' press slept +'a' relased +'a' release slept +'s' pressed +'s' press slept +'s' relased +'s' release slept +``` + +> **NOTE** remember to use `await asyncio.sleep(...)` in async callbacks +instead of `time.sleep(...)` or the timings will fail: + +### Stop listening + +You can change the key that ends the listening by giving `until` parameter, +which defaults to `"esc"`: + +```python +# ... +listen_keyboard( + on_press=press, + until="space", +) +``` + +You also can manually stop listening by calling `stop_listening()` from the +callback or from some other function: + +```python +from sshkeyboard import listen_keyboard, stop_listening + +def press(key): + print(f"'{key}' pressed") + if key == "z": + stop_listening() + +listen_keyboard(on_press=press) +``` + +`until` can be also set to `None`. This means that listening ends only with +`stop_listening()` or if an error has been raised. + +### Troubleshooting + +If some keys do not seem to register correctly, try turning the debug mode on. +This will add logs if some keys are skipped intentionally: + +```python +# ... +listen_keyboard( + on_press=press, + debug=True, +) +``` + +If one key press causes multiple `on_press` / `on_release` callbacks or if +releasing happens too slowly, you can try to tweak the default timing +parameters: + +```python +# ... +listen_keyboard( + on_press=press, + delay_second_char=0.75, + delay_other_chars=0.05, +) +``` + +### More + +Check out the full +[reference](https://sshkeyboard.readthedocs.io/en/latest/reference.html) +for more functions and parameters such as: + +- `lower` parameter +- `sleep` parameter +- `max_thread_pool_workers` parameter +- `listen_keyboard_manual` function + +Direct links to functions: + +- [listen_keyboard](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.listen_keyboard) +- [stop_listening](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.stop_listening) +- [listen_keyboard_manual](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.listen_keyboard_manual) + +## Development + +This sections explains how to build the documentation and how to run the +[pre-commit script](https://github.com/ollipal/sshkeyboard/blob/main/pre-commit) +locally. This helps if you want to create +[a pull request](https://github.com/ollipal/sshkeyboard/pulls) +or if you just want to try things out. + +Building the documentations allows you to build all of the files served on the +[documentation](https://sshkeyboard.readthedocs.io) site locally. + +The +[pre-commit script](https://github.com/ollipal/sshkeyboard/blob/main/pre-commit) +handles running tests, formatting and +linting before each Git commit. These same checks also run automatically on +[Github Actions](https://github.com/ollipal/sshkeyboard/blob/main/.github/workflows/main.yml). + +Start by cloning this library, and change directory to the project root: + +```text +git clone git@github.com:ollipal/sshkeyboard.git +cd sshkeyboard +``` + +Optionally, create and activate a virtual environment at the root of the +project (you might need to use `python3` keyword instead of `python`): + +```text +python -m venv .env +source .env/bin/activate +``` + +(Later you can deactivate the virtual environment with: `deactivate`) + +To build the documentation or run the pre-commit script locally, you need +to install the development dependencies: + +```text +pip install -r dev-requirements.txt +``` + +### Documentation + +To build the documentation locally, first change into `docs/` directory: + +```text +cd docs +``` + +Then to build the documentation, call: + +```text +make html +``` + +Now you should have a new `docs/build/` directory, and you can open +`<your-clone-path>/sshkeyboard/docs/build/html/index.html` from your browser. + +You can force the rebuild by running: + +```text +rm -rf build/ && make html +``` + +You can change the documentation content by changing `README.md` or files from +`src/` or `docs/source/`. If you are mainly changing contents from +`docs/source/`, you can enable automatic re-building by running: + +```text +sphinx-autobuild ./source/ ./build/html/ +``` + +### Running the pre-commit script + +You can run the **tests** +([tox](https://tox.wiki/en/latest/index.html), +[pytest](https://docs.pytest.org)), **formatting** +([black](https://black.readthedocs.io/en/stable/), +[isort](https://pycqa.github.io/isort/)) and **linting** +([pflake8](https://github.com/csachs/pyproject-flake8), +[pep8-naming](https://github.com/PyCQA/pep8-naming), +[codespell](https://github.com/codespell-project/codespell), +[markdownlint](https://github.com/markdownlint/markdownlint)) simply by +executing: + +```text +./pre-commit +``` + +Now if you want to automatically run these when you call `git commit`, copy +the script into `.git/hooks/` directory: + +```text +cp pre-commit .git/hooks +``` + +> **NOTE**: this process does not run `markdownlint` by default as it +requires [Ruby](https://www.ruby-lang.org/en/) to be installed. If you want +to run `markdownlint` locally as well, +[install Ruby](https://www.ruby-lang.org/en/documentation/installation/) +and install markdown lint with `gem install mdl -v 0.11.0`. Then from +`pre-commit` change `RUN_MDL=false` to `RUN_MDL=true`. (You need to copy the +file again into `.git/hooks/` if you did that earlier) + +## Comparison to other keyboard libraries + +The other keyboard libraries work by reading proper keycodes from the system. + +This means that they usually require either +[X server](https://en.wikipedia.org/wiki/X_Window_System) or +[uinput](https://www.kernel.org/doc/html/v4.12/input/uinput.html), so they do +not work over SSH. But this means they do not have the same +[limitations](#how-it-works) as this library. + +They usually can also support more features such as pressing the keys instead +of just reacting to user input. + +I have good experiences from these libraries: + +- [pynput](https://pynput.readthedocs.io/en/latest/) +- [keyboard](https://github.com/boppreh/keyboard) (requires sudo) + +%package help +Summary: Development documents and examples for sshkeyboard +Provides: python3-sshkeyboard-doc +%description help +# sshkeyboard + +The only keyboard event callback library that works _everywhere_, even when +used through an [SSH](https://en.wikipedia.org/wiki/Secure_Shell) connection +(hence the name). + +It works with headless computers and servers, or for example inside Windows +Subsystem for Linux (WSL 2). One good use case is controlling Raspberry Pi +based robots or RC cars through SSH. Note that this library can also be used +locally without an SSH connection. + +It does not depend on X server, uinput, root access (sudo) or +any external dependencies. + +Supports [asyncio](https://docs.python.org/3/library/asyncio.html) and +sequential/concurrent callback modes. For Python 3.6+. + +[Documentation](https://sshkeyboard.readthedocs.io) - +[Github source](https://github.com/ollipal/sshkeyboard) - +[PyPI](https://pypi.org/project/sshkeyboard/) - +[Reference](https://sshkeyboard.readthedocs.io/en/latest/reference.html) - +[](https://pepy.tech/project/sshkeyboard) + +## Quick start + +Installation: + +```text +pip install sshkeyboard +``` + +Simple example to fire events when a key is pressed or released. +`esc` key ends listening by default: + +```python +from sshkeyboard import listen_keyboard + +def press(key): + print(f"'{key}' pressed") + +def release(key): + print(f"'{key}' released") + +listen_keyboard( + on_press=press, + on_release=release, +) +``` + +Output: + +```text +$ python example.py +'a' pressed +'a' released +``` + +## How it works + +The sshkeyboard library works without +[X server](https://en.wikipedia.org/wiki/X_Window_System) +and [uinput](https://www.kernel.org/doc/html/v4.12/input/uinput.html). + +On Unix based systems (such as Linux, macOS) it works by parsing characters +from [sys.stdin](https://docs.python.org/3/library/sys.html#sys.stdin). This +is done with [fcntl](https://docs.python.org/3/library/fcntl.html) and +[termios](https://docs.python.org/3/library/termios.html) standard library +modules. + +On Windows [msvcrt](https://docs.python.org/3/library/msvcrt.html) standard +library module is used to read user input. The Windows support is still new, +so please create [an issue](https://github.com/ollipal/sshkeyboard/issues) +if you run into problems. + +This behaviour allows it to work where other libraries like +[pynput](#comparison-to-other-keyboard-libraries) or +[keyboard](#comparison-to-other-keyboard-libraries) do not work, but +it comes with some **limitations**, mainly: + +1. Holding multiple keys down at the same time does not work, the library + releases the previous keys when a new one is pressed. Releasing keys also + happens after a short delay, and some key presses can get lost if the same + key gets spammed fast. +2. Some keys do not write to `sys.stdin` when pressed, such as `Ctrl`, + `Shift`, `Caps Lock`, `Alt` and `Windows`/`Command`/`Super` key. That is + why this library does not attempt to parse those even if they could be + technically be parsed in some cases + +## Advanced use + +### Sequential mode + +Normally this library allows `on_press` and `on_release` callbacks to be run +concurrently. This means that by running: + +```python +import time +from sshkeyboard import listen_keyboard + +def press(key): + print(f"'{key}' pressed") + time.sleep(3) + print(f"'{key}' slept") + +listen_keyboard(on_press=press) +``` + +and pressing `"a"`, `"s"` and `"d"` keys will log: + +```text +'a' pressed +'s' pressed +'d' pressed +'a' slept +'s' slept +'d' slept +``` + +But sometimes you don't want to allow the callbacks to overlap, then +you should set `sequential` parameter to `True`: + +```python +# ... +listen_keyboard( + on_press=press, + sequential=True, +) +``` + +Then pressing `"a"`, `"s"` and `"d"` keys will log: + +```text +'a' pressed +'a' slept +'s' pressed +'s' slept +'d' pressed +'d' slept +``` + +### Asyncio + +You can also use asynchronous functions as `on_press` / `on_release` callbacks +with `listen_keyboard`: + +```python +import asyncio +from sshkeyboard import listen_keyboard + +async def press(key): + print(f"'{key}' pressed") + await asyncio.sleep(3) + print(f"'{key}' slept") + +listen_keyboard(on_press=press) +``` + +> **NOTE** remember to use `await asyncio.sleep(...)` in async callbacks +instead of `time.sleep(...)` or the timings will fail: + +### Mixing asynchronous and concurrent callbacks + +`listen_keyboard` also supports mixing asynchronous and concurrent callbacks: + +```python +import asyncio +import time +from sshkeyboard import listen_keyboard + +async def press(key): + print(f"'{key}' pressed") + await asyncio.sleep(3) + print(f"'{key}' press slept") + +def release(key): + print(f"'{key}' relased") + time.sleep(3) + print(f"'{key}' release slept") + +listen_keyboard( + on_press=press, + on_release=release, +) +``` + +Here pressing `"a"` and `"s"` will log: + +```text +'a' pressed +'a' relased +'s' pressed +'s' relased +'a' press slept +'s' press slept +'a' release slept +'s' release slept +``` + +And with `sequential=True`: + +```python +# ... +listen_keyboard( + on_press=press, + on_release=release, + sequential=True, +) +``` + +will log: + +```text +'a' pressed +'a' press slept +'a' relased +'a' release slept +'s' pressed +'s' press slept +'s' relased +'s' release slept +``` + +> **NOTE** remember to use `await asyncio.sleep(...)` in async callbacks +instead of `time.sleep(...)` or the timings will fail: + +### Stop listening + +You can change the key that ends the listening by giving `until` parameter, +which defaults to `"esc"`: + +```python +# ... +listen_keyboard( + on_press=press, + until="space", +) +``` + +You also can manually stop listening by calling `stop_listening()` from the +callback or from some other function: + +```python +from sshkeyboard import listen_keyboard, stop_listening + +def press(key): + print(f"'{key}' pressed") + if key == "z": + stop_listening() + +listen_keyboard(on_press=press) +``` + +`until` can be also set to `None`. This means that listening ends only with +`stop_listening()` or if an error has been raised. + +### Troubleshooting + +If some keys do not seem to register correctly, try turning the debug mode on. +This will add logs if some keys are skipped intentionally: + +```python +# ... +listen_keyboard( + on_press=press, + debug=True, +) +``` + +If one key press causes multiple `on_press` / `on_release` callbacks or if +releasing happens too slowly, you can try to tweak the default timing +parameters: + +```python +# ... +listen_keyboard( + on_press=press, + delay_second_char=0.75, + delay_other_chars=0.05, +) +``` + +### More + +Check out the full +[reference](https://sshkeyboard.readthedocs.io/en/latest/reference.html) +for more functions and parameters such as: + +- `lower` parameter +- `sleep` parameter +- `max_thread_pool_workers` parameter +- `listen_keyboard_manual` function + +Direct links to functions: + +- [listen_keyboard](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.listen_keyboard) +- [stop_listening](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.stop_listening) +- [listen_keyboard_manual](https://sshkeyboard.readthedocs.io/en/latest/reference.html#sshkeyboard.listen_keyboard_manual) + +## Development + +This sections explains how to build the documentation and how to run the +[pre-commit script](https://github.com/ollipal/sshkeyboard/blob/main/pre-commit) +locally. This helps if you want to create +[a pull request](https://github.com/ollipal/sshkeyboard/pulls) +or if you just want to try things out. + +Building the documentations allows you to build all of the files served on the +[documentation](https://sshkeyboard.readthedocs.io) site locally. + +The +[pre-commit script](https://github.com/ollipal/sshkeyboard/blob/main/pre-commit) +handles running tests, formatting and +linting before each Git commit. These same checks also run automatically on +[Github Actions](https://github.com/ollipal/sshkeyboard/blob/main/.github/workflows/main.yml). + +Start by cloning this library, and change directory to the project root: + +```text +git clone git@github.com:ollipal/sshkeyboard.git +cd sshkeyboard +``` + +Optionally, create and activate a virtual environment at the root of the +project (you might need to use `python3` keyword instead of `python`): + +```text +python -m venv .env +source .env/bin/activate +``` + +(Later you can deactivate the virtual environment with: `deactivate`) + +To build the documentation or run the pre-commit script locally, you need +to install the development dependencies: + +```text +pip install -r dev-requirements.txt +``` + +### Documentation + +To build the documentation locally, first change into `docs/` directory: + +```text +cd docs +``` + +Then to build the documentation, call: + +```text +make html +``` + +Now you should have a new `docs/build/` directory, and you can open +`<your-clone-path>/sshkeyboard/docs/build/html/index.html` from your browser. + +You can force the rebuild by running: + +```text +rm -rf build/ && make html +``` + +You can change the documentation content by changing `README.md` or files from +`src/` or `docs/source/`. If you are mainly changing contents from +`docs/source/`, you can enable automatic re-building by running: + +```text +sphinx-autobuild ./source/ ./build/html/ +``` + +### Running the pre-commit script + +You can run the **tests** +([tox](https://tox.wiki/en/latest/index.html), +[pytest](https://docs.pytest.org)), **formatting** +([black](https://black.readthedocs.io/en/stable/), +[isort](https://pycqa.github.io/isort/)) and **linting** +([pflake8](https://github.com/csachs/pyproject-flake8), +[pep8-naming](https://github.com/PyCQA/pep8-naming), +[codespell](https://github.com/codespell-project/codespell), +[markdownlint](https://github.com/markdownlint/markdownlint)) simply by +executing: + +```text +./pre-commit +``` + +Now if you want to automatically run these when you call `git commit`, copy +the script into `.git/hooks/` directory: + +```text +cp pre-commit .git/hooks +``` + +> **NOTE**: this process does not run `markdownlint` by default as it +requires [Ruby](https://www.ruby-lang.org/en/) to be installed. If you want +to run `markdownlint` locally as well, +[install Ruby](https://www.ruby-lang.org/en/documentation/installation/) +and install markdown lint with `gem install mdl -v 0.11.0`. Then from +`pre-commit` change `RUN_MDL=false` to `RUN_MDL=true`. (You need to copy the +file again into `.git/hooks/` if you did that earlier) + +## Comparison to other keyboard libraries + +The other keyboard libraries work by reading proper keycodes from the system. + +This means that they usually require either +[X server](https://en.wikipedia.org/wiki/X_Window_System) or +[uinput](https://www.kernel.org/doc/html/v4.12/input/uinput.html), so they do +not work over SSH. But this means they do not have the same +[limitations](#how-it-works) as this library. + +They usually can also support more features such as pressing the keys instead +of just reacting to user input. + +I have good experiences from these libraries: + +- [pynput](https://pynput.readthedocs.io/en/latest/) +- [keyboard](https://github.com/boppreh/keyboard) (requires sudo) + +%prep +%autosetup -n sshkeyboard-2.3.1 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-sshkeyboard -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Thu May 18 2023 Python_Bot <Python_Bot@openeuler.org> - 2.3.1-1 +- Package Spec generated @@ -0,0 +1 @@ +f8c08df60ce10776b03130e81a71370c sshkeyboard-2.3.1.tar.gz |