From a7d57469b0dd1d11ef1c121291f21c039bcc283d Mon Sep 17 00:00:00 2001 From: Paolo Lammens Date: Wed, 8 Jun 2022 11:29:27 +0200 Subject: [PATCH 1/2] fix: Clear O_NONBLOCK flag after using ainput() This is to ensure we can still use regular blocking IO such as input() and print() after using ainput. Fixes #17, #19 --- src/loveletter_cli/session.py | 3 ++- src/loveletter_cli/ui/input.py | 42 +++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/loveletter_cli/session.py b/src/loveletter_cli/session.py index 7042cce..3d18617 100644 --- a/src/loveletter_cli/session.py +++ b/src/loveletter_cli/session.py @@ -9,7 +9,6 @@ import more_itertools as mitt import valid8 -from aioconsole import ainput, aprint from multimethod import multimethod import loveletter.game @@ -22,6 +21,8 @@ from loveletter_cli.exceptions import Restart from loveletter_cli.server_process import ServerProcess from loveletter_cli.ui import ( + ainput, + aprint, async_ask_valid_input, draw_game, pause, diff --git a/src/loveletter_cli/ui/input.py b/src/loveletter_cli/ui/input.py index 4414b03..d50c1ca 100644 --- a/src/loveletter_cli/ui/input.py +++ b/src/loveletter_cli/ui/input.py @@ -1,11 +1,13 @@ import enum import functools +import os +import sys import textwrap from typing import Callable, Tuple, Type, TypeVar +import aioconsole import more_itertools import valid8 -from aioconsole import ainput, aprint from .misc import printable_width @@ -14,6 +16,42 @@ _DEFAULT = object() +# Define ainput() based on OS: if the OS uses the O_NONBLOCK flag, we have to +# clear it after every call to ainput() to ensure compatibility with blocking +# IO such as print() and input(). +if hasattr(os, "set_blocking"): + + @functools.wraps(aioconsole.ainput) + async def ainput(*args, **kwargs): + result = await aioconsole.ainput(*args, **kwargs) + os.set_blocking(sys.stdin.fileno(), True) + return result + + + @functools.wraps(aioconsole.ainput) + async def aprint(*args, **kwargs): + result = await aioconsole.aprint(*args, **kwargs) + os.set_blocking(sys.stdin.fileno(), True) + return result + +else: + ainput = aioconsole.ainput + aprint = aioconsole.aprint + + +def ask_valid_input(*args, **kwargs) -> _T: + error_message, parser, prompt, validation_errors = _ask_valid_input_parse_args( + *args, **kwargs + ) + + while True: + raw_input = input(prompt) + try: + return _parse_input(raw_input, parser, error_message, validation_errors) + except (valid8.ValidationError, *validation_errors): + continue + + async def async_ask_valid_input(*args, **kwargs): """Asynchronous version of :func:`ask_valid_input`.""" error_message, parser, prompt, validation_errors = _ask_valid_input_parse_args( @@ -156,4 +194,6 @@ async def pause() -> None: # the user has to enter twice before input is detected; # but the asynchronous nature is needed to ensure other events are handled in time # (e.g. when the connection is lost). + # Also caused trouble on Linux and Unix regarding the O_NONBLOCK flag + # (see #17 and #19) but this has been fixed. await ainput("Enter something to continue... ") From 30839f2f0907a710ff358d19ee094eb6868bdb50 Mon Sep 17 00:00:00 2001 From: Paolo Lammens Date: Tue, 10 Jan 2023 01:09:26 +0100 Subject: [PATCH 2/2] fix: Revert back to regular input() in pause() --- src/loveletter_cli/ui/input.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/loveletter_cli/ui/input.py b/src/loveletter_cli/ui/input.py index d50c1ca..e576810 100644 --- a/src/loveletter_cli/ui/input.py +++ b/src/loveletter_cli/ui/input.py @@ -27,7 +27,6 @@ async def ainput(*args, **kwargs): os.set_blocking(sys.stdin.fileno(), True) return result - @functools.wraps(aioconsole.ainput) async def aprint(*args, **kwargs): result = await aioconsole.aprint(*args, **kwargs) @@ -190,10 +189,4 @@ def _decorate_prompt(prompt: str) -> str: async def pause() -> None: - # Using ainput() instead of regular input() sometimes causes trouble: - # the user has to enter twice before input is detected; - # but the asynchronous nature is needed to ensure other events are handled in time - # (e.g. when the connection is lost). - # Also caused trouble on Linux and Unix regarding the O_NONBLOCK flag - # (see #17 and #19) but this has been fixed. - await ainput("Enter something to continue... ") + input("Enter something to continue... ")