cli-ih 0.6.2.1__py3-none-any.whl → 0.6.3__py3-none-any.whl
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.
- cli_ih/asyncClient.py +38 -14
- cli_ih/client.py +1 -1
- {cli_ih-0.6.2.1.dist-info → cli_ih-0.6.3.dist-info}/METADATA +1 -1
- cli_ih-0.6.3.dist-info/RECORD +8 -0
- cli_ih-0.6.2.1.dist-info/RECORD +0 -8
- {cli_ih-0.6.2.1.dist-info → cli_ih-0.6.3.dist-info}/WHEEL +0 -0
- {cli_ih-0.6.2.1.dist-info → cli_ih-0.6.3.dist-info}/top_level.txt +0 -0
cli_ih/asyncClient.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
from typing import Coroutine
|
|
1
|
+
from typing import Coroutine, Callable, Any
|
|
2
2
|
from .exceptions import HandlerClosed
|
|
3
|
-
import logging, warnings, asyncio, inspect
|
|
3
|
+
import logging, warnings, asyncio, inspect, threading
|
|
4
4
|
|
|
5
5
|
class AsyncInputHandler:
|
|
6
6
|
def __init__(self, cursor = "", *, logger: logging.Logger | None = None, register_defaults: bool = True):
|
|
7
7
|
self.commands = {}
|
|
8
8
|
self.is_running = False
|
|
9
|
-
self.cursor = f"{cursor.strip()} "
|
|
9
|
+
self.cursor = f"{cursor.strip()} " if cursor else ""
|
|
10
10
|
self.global_logger = logger if logger else None
|
|
11
11
|
self.logger = logger.getChild("InputHandler") if logger else None
|
|
12
12
|
self.register_defaults = register_defaults
|
|
@@ -48,7 +48,7 @@ class AsyncInputHandler:
|
|
|
48
48
|
else:
|
|
49
49
|
print(f"[EXEPTION]: {msg}: {e}")
|
|
50
50
|
|
|
51
|
-
def __register_cmd(self, name: str, func:
|
|
51
|
+
def __register_cmd(self, name: str, func: Callable[..., Any], description: str = "", legacy=False):
|
|
52
52
|
name = name.lower()
|
|
53
53
|
if not description:
|
|
54
54
|
description = "A command"
|
|
@@ -56,16 +56,16 @@ class AsyncInputHandler:
|
|
|
56
56
|
raise SyntaxError("Command name must not have spaces")
|
|
57
57
|
if name in self.commands:
|
|
58
58
|
raise SyntaxError(f"Command '{name}' is already registered. If theese commands have a different case and they need to stay the same, downgrade the package version to 0.5.x")
|
|
59
|
-
self.commands[name] = {"cmd": func, "description": description, "legacy": legacy
|
|
59
|
+
self.commands[name] = {"cmd": func, "description": description, "legacy": legacy}
|
|
60
60
|
|
|
61
|
-
def register_command(self, name: str, func:
|
|
61
|
+
def register_command(self, name: str, func: Callable[..., Any], description: str = ""):
|
|
62
62
|
"""(DEPRECATED) Registers a command with its associated function."""
|
|
63
63
|
warnings.warn("Registering commands with `register_command` is deprecated, and should not be used.", DeprecationWarning, 2)
|
|
64
64
|
self.__register_cmd(name, func, description, legacy=True)
|
|
65
65
|
|
|
66
66
|
def command(self, *, name: str = "", description: str = ""):
|
|
67
67
|
"""Registers a command with its associated function as a decorator."""
|
|
68
|
-
def decorator(func:
|
|
68
|
+
def decorator(func: Callable[..., Any]):
|
|
69
69
|
lname = name or func.__name__
|
|
70
70
|
self.__register_cmd(lname, func, description)
|
|
71
71
|
return func
|
|
@@ -74,16 +74,32 @@ class AsyncInputHandler:
|
|
|
74
74
|
async def start(self):
|
|
75
75
|
"""Starts the input handler loop in a separate thread if thread mode is enabled."""
|
|
76
76
|
self.is_running = True
|
|
77
|
+
loop = asyncio.get_running_loop()
|
|
78
|
+
input_queue = asyncio.Queue()
|
|
79
|
+
|
|
80
|
+
def _input_worker():
|
|
81
|
+
while self.is_running:
|
|
82
|
+
try:
|
|
83
|
+
text = input(self.cursor)
|
|
84
|
+
loop.call_soon_threadsafe(input_queue.put_nowait, text)
|
|
85
|
+
except EOFError:
|
|
86
|
+
loop.call_soon_threadsafe(input_queue.put_nowait, EOFError)
|
|
87
|
+
break
|
|
88
|
+
except Exception:
|
|
89
|
+
break
|
|
90
|
+
|
|
91
|
+
thread = threading.Thread(target=_input_worker, daemon=True)
|
|
92
|
+
thread.start()
|
|
77
93
|
|
|
78
94
|
async def _run_command(commands: dict, name: str, args: list):
|
|
79
95
|
"""Executes a command from the command dictionary if it exists."""
|
|
80
96
|
command = commands.get(name)
|
|
81
97
|
if not command:
|
|
82
98
|
self.__warning(f"Command '{name}' not found.")
|
|
99
|
+
return
|
|
83
100
|
|
|
84
101
|
func = command.get("cmd")
|
|
85
102
|
is_legacy = command.get("legacy", False)
|
|
86
|
-
is_async = command.get("is_async", False)
|
|
87
103
|
|
|
88
104
|
if not callable(func):
|
|
89
105
|
raise ValueError(f"The command '{name}' is not callable.")
|
|
@@ -101,12 +117,12 @@ class AsyncInputHandler:
|
|
|
101
117
|
try:
|
|
102
118
|
if is_legacy:
|
|
103
119
|
warnings.warn("This way of running commands id Deprecated. And should be changed to the new decorator way.", DeprecationWarning, 2)
|
|
104
|
-
if
|
|
120
|
+
if inspect.iscoroutinefunction(func):
|
|
105
121
|
await func(args)
|
|
106
122
|
else:
|
|
107
123
|
await asyncio.to_thread(func, args)
|
|
108
124
|
else:
|
|
109
|
-
if
|
|
125
|
+
if inspect.iscoroutinefunction(func):
|
|
110
126
|
await func(*args)
|
|
111
127
|
else:
|
|
112
128
|
await asyncio.to_thread(func, *args)
|
|
@@ -118,7 +134,15 @@ class AsyncInputHandler:
|
|
|
118
134
|
|
|
119
135
|
while self.is_running:
|
|
120
136
|
try:
|
|
121
|
-
|
|
137
|
+
try:
|
|
138
|
+
user_input = await asyncio.wait_for(input_queue.get(), timeout=0.1)
|
|
139
|
+
except asyncio.TimeoutError:
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
if user_input is EOFError:
|
|
143
|
+
self.__error("Input ended unexpectedly.")
|
|
144
|
+
break
|
|
145
|
+
|
|
122
146
|
if not user_input:
|
|
123
147
|
continue
|
|
124
148
|
|
|
@@ -142,14 +166,14 @@ class AsyncInputHandler:
|
|
|
142
166
|
|
|
143
167
|
def register_default_commands(self):
|
|
144
168
|
@self.command(name="help", description="Displays all the available commands")
|
|
145
|
-
def help():
|
|
169
|
+
async def help(*args):
|
|
146
170
|
str_out = "Available commands:\n"
|
|
147
171
|
for command, data in self.commands.items():
|
|
148
172
|
str_out += f" {command}: {data['description']}\n"
|
|
149
173
|
print(str_out)
|
|
150
174
|
|
|
151
175
|
@self.command(name="debug", description="If a logger is present changes the logging level to DEBUG.")
|
|
152
|
-
def debug_mode():
|
|
176
|
+
async def debug_mode(*args):
|
|
153
177
|
logger = self.global_logger
|
|
154
178
|
if not logger:
|
|
155
179
|
return self.__warning("No logger defined for this InputHandler instance.")
|
|
@@ -169,5 +193,5 @@ class AsyncInputHandler:
|
|
|
169
193
|
self.__info(message)
|
|
170
194
|
|
|
171
195
|
@self.command(name="exit", description="Exits the Input Handler irreversibly.")
|
|
172
|
-
def exit_thread():
|
|
196
|
+
async def exit_thread(*args):
|
|
173
197
|
raise HandlerClosed("Handler was closed with exit command.")
|
cli_ih/client.py
CHANGED
|
@@ -7,7 +7,7 @@ class InputHandler:
|
|
|
7
7
|
self.commands = {}
|
|
8
8
|
self.is_running = False
|
|
9
9
|
self.thread_mode = thread_mode
|
|
10
|
-
self.cursor = f"{cursor.strip()} "
|
|
10
|
+
self.cursor = f"{cursor.strip()} " if cursor else ""
|
|
11
11
|
self.thread = None
|
|
12
12
|
self.global_logger = logger if logger else None
|
|
13
13
|
self.logger = logger.getChild("InputHandler") if logger else None
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
cli_ih/__init__.py,sha256=0dtZNjrIlZMny9M0s6ygYTuo-9sM7BCSJHkBMDYkn8g,247
|
|
2
|
+
cli_ih/asyncClient.py,sha256=VNjBwO5Y0IVl5Gv_oq-GR0GpmnM2jk6gBH08z9VjaKM,7939
|
|
3
|
+
cli_ih/client.py,sha256=WGlA8sxvF173eKEhVbrk_Z3TjHRHIBZzum1rsvE9rsY,7786
|
|
4
|
+
cli_ih/exceptions.py,sha256=0xqaMCVu-yEURIrB6wEhbf6kfdsRmODJBoDsQTOp29s,156
|
|
5
|
+
cli_ih-0.6.3.dist-info/METADATA,sha256=9Qyw0eFfA3RQp9WxRnoY2cJucjqQBcu29kLJrO2odYc,2789
|
|
6
|
+
cli_ih-0.6.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
cli_ih-0.6.3.dist-info/top_level.txt,sha256=Ve1CRLNXhPyPSkpN0xLu26roh30LQCpNzkF61BZYfk0,7
|
|
8
|
+
cli_ih-0.6.3.dist-info/RECORD,,
|
cli_ih-0.6.2.1.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
cli_ih/__init__.py,sha256=0dtZNjrIlZMny9M0s6ygYTuo-9sM7BCSJHkBMDYkn8g,247
|
|
2
|
-
cli_ih/asyncClient.py,sha256=jnoq7v7tgNrAi0u12GamNhMD8VyPa2NWrRy0ii53M_Y,7000
|
|
3
|
-
cli_ih/client.py,sha256=Mka6UmhS9wSFVGNqqsNIZ6cYON8HWnYTudkZWiPdmgI,7768
|
|
4
|
-
cli_ih/exceptions.py,sha256=0xqaMCVu-yEURIrB6wEhbf6kfdsRmODJBoDsQTOp29s,156
|
|
5
|
-
cli_ih-0.6.2.1.dist-info/METADATA,sha256=dQS5zWTr_EhCBSLLKN10q2PHG_1FJ32i8RZs9SUyuiU,2791
|
|
6
|
-
cli_ih-0.6.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
-
cli_ih-0.6.2.1.dist-info/top_level.txt,sha256=Ve1CRLNXhPyPSkpN0xLu26roh30LQCpNzkF61BZYfk0,7
|
|
8
|
-
cli_ih-0.6.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|