Compare commits

..

No commits in common. "master" and "v1.1" have entirely different histories.
master ... v1.1

7 changed files with 56 additions and 161 deletions

6
.gitignore vendored
View File

@ -128,10 +128,4 @@ dmypy.json
# Pyre type checker # Pyre type checker
.pyre/ .pyre/
# Ignore .idea
.idea/ .idea/
# ignore Sonar
codecov
.scannerwork/

View File

@ -1,11 +1,4 @@
# CLI in Python # CLI in Python
<p align="center">
<img src="https://img.shields.io/github/license/SantaSpeen/CLI-in-Python?style=for-the-badge" alt="license" title="license: MIT">
<img src="https://img.shields.io/github/issues/SantaSpeen/CLI-in-Python?style=for-the-badge" alt="issues">
<img src="./assets/magic_logo.svg" alt="magic">
<br/>
<img src="./assets/preview.png" alt="preview">
</p>
##### Версия для русских: [здесь](./README_RU.md) ##### Версия для русских: [здесь](./README_RU.md)
@ -59,7 +52,7 @@ cli.write("cli.write")
# ]: cli.write # ]: cli.write
``` ```
* With `logging` output usage * With logging output usage
```python ```python
from console import Console from console import Console
@ -82,7 +75,7 @@ logging.info("Info log")
# ]: 2022-02-20 23:22:49,731 - root - INFO - Info log # ]: 2022-02-20 23:22:49,731 - root - INFO - Info log
``` ```
* With `print()` and `console.log` output usage * with `print()` and `console.log` output usage
```python ```python
from console import Console from console import Console
@ -120,4 +113,3 @@ Copy all from `builtins_fix.pyi` and insert into `builtins.pyi` at line `131` be
Used in: Used in:
* [Python-CLI-Game-Engine](https://github.com/SantaSpeen/Python-CLI-Game-Engine) * [Python-CLI-Game-Engine](https://github.com/SantaSpeen/Python-CLI-Game-Engine)
* [CLI-Remote-in-Python](https://github.com/SantaSpeen/CLI-Remote-in-Python)

View File

@ -1,11 +1,4 @@
# CLI in Python # CLI in Python
<p align="center">
<img src="https://img.shields.io/github/license/SantaSpeen/CLI-in-Python?style=for-the-badge" alt="license" title="license: MIT">
<img src="https://img.shields.io/github/issues/SantaSpeen/CLI-in-Python?style=for-the-badge" alt="issues">
<img src="./assets/magic_logo.svg" alt="magic">
<br/>
<img src="./assets/preview.png" alt="preview">
</p>
## Консольная оболочка для программ на Python3 ## Консольная оболочка для программ на Python3
@ -57,7 +50,7 @@ cli.write("cli.write")
# ]: cli.write # ]: cli.write
``` ```
* Использование вывода с `logging` * Использование вывода с logging
```python ```python
from console import Console from console import Console
@ -80,7 +73,7 @@ logging.info("Info log")
# ]: 2022-02-20 23:22:49,731 - root - INFO - Info log # ]: 2022-02-20 23:22:49,731 - root - INFO - Info log
``` ```
* Использование вывода с `print()` и `console.log` * Использование вывода с`print()` и `console.log`
```python ```python
from console import Console from console import Console
@ -108,14 +101,13 @@ console << "<< log"
# ]: << log # ]: << log
``` ```
Если вы используете IDE, можно обновить `builtins.pyi`, что бы она не ругалась на отсутствие `console.*` используя `scr/builtins_fix.pyi`. <br/> Если вы используете IDE, можно обновить `builtins.pyi` используя `scr/builtins_fix.pyi`. <br/>
Скопируйте всё из `builtins_fix.pyi` и вставте в `builtins.pyi` на `131` линию, перед `class type(object)`. Скопируйте всё из `builtins_fix.pyi` и вставте в `builtins.pyi` на `131` линию, до `class type(object)`.
## Ссылки ## Ссылки
* [Мой Telegram](https://t.me/SantaSpeen "SantaSpeen"): https://t.me/SantaSpeen * [Мой Telegram](https://t.me/SantaSpeen "SantaSpeen"): https://t.me/SantaSpeen
Используемые в проектах: Используемые в поектах:
* [Python-CLI-Game-Engine](https://github.com/SantaSpeen/Python-CLI-Game-Engine) * [Python-CLI-Game-Engine](https://github.com/SantaSpeen/Python-CLI-Game-Engine)
* [CLI-Remote-in-Python](https://github.com/SantaSpeen/CLI-Remote-in-Python)

View File

@ -1,40 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="180.5" height="28" role="img" aria-label="MADE WITH: MAGIC">
<title>MADE WITH: MAGIC</title>
<g shape-rendering="crispEdges">
<rect width="100.25" height="28" fill="#555"/>
<rect x="100.25" width="80.25" height="28" fill="#fe7d37"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100">
<svg x="3"
y="4"
id="Capa_1"
height="20"
viewBox="0 0 512 512"
width="20"
xmlns="http://www.w3.org/2000/svg">
<g>
<path d="m395.82 182.616-188.72 188.72-12.91 1.72-9.35 20.54-34.31 34.31-11.01-.73-11.25 22.99-56.48 56.48c-2.93 2.93-6.77 4.39-10.61 4.39s-7.68-1.46-10.61-4.39l-22.62-22.62h-.01l-22.62-22.63c-5.86-5.86-5.86-15.36 0-21.22l77.63-77.63 16.6-7.03 5.66-15.23 34.31-34.31 14.84-4.92 7.42-17.34 167.57-167.57 33.24 33.24z" fill="#f66"/>
<path d="m395.82 116.146v66.47l-188.72 188.72-12.91 1.72-9.35 20.54-34.31 34.31-11.01-.73-11.25 22.99-56.48 56.48c-2.93 2.93-6.77 4.39-10.61 4.39s-7.68-1.46-10.61-4.39l-22.62-22.62 334.64-334.64z" fill="#e62e6b"/>
<path d="m506.61 209.006-69.14-69.13 43.05-88.38c2.8-5.75 1.65-12.65-2.88-17.17-4.52-4.53-11.42-5.68-17.17-2.88l-88.38 43.05-69.13-69.14c-4.35-4.35-10.92-5.6-16.56-3.16-5.65 2.45-9.23 8.09-9.04 14.24l2.86 90.45-85.37 57.83c-4.91 3.32-7.4 9.22-6.36 15.04 1.04 5.83 5.4 10.51 11.15 11.94l96.62 24.01 24.01 96.62c1.43 5.75 6.11 10.11 11.94 11.15.87.16 1.75.23 2.62.23 4.92 0 9.6-2.42 12.42-6.59l57.83-85.37 90.45 2.86c6.14.19 11.79-3.39 14.24-9.04 2.44-5.64 1.19-12.21-3.16-16.56z" fill="#fabe2c"/>
<path d="m296.26 215.706 24.01 96.62c1.43 5.75 6.11 10.11 11.94 11.15.87.16 1.75.23 2.62.23 4.92 0 9.6-2.42 12.42-6.59l57.83-85.37 90.45 2.86c6.14.19 11.79-3.39 14.24-9.04 2.44-5.64 1.19-12.21-3.16-16.56l-69.14-69.13 43.05-88.38c2.8-5.75 1.65-12.65-2.88-17.17z" fill="#fd9025"/>
<path d="m465 416.966c-25.92 0-47 21.08-47 47s21.08 47 47 47 47-21.08 47-47-21.08-47-47-47z" fill="#fabe2c"/>
<path d="m104 28.966h-13v-13c0-8.284-6.716-15-15-15s-15 6.716-15 15v13h-13c-8.284 0-15 6.716-15 15s6.716 15 15 15h13v13c0 8.284 6.716 15 15 15s15-6.716 15-15v-13h13c8.284 0 15-6.716 15-15s-6.716-15-15-15z" fill="#fed843"/>
<path d="m207.1 371.336-22.26 22.26-45.32-87.62 22.26-22.26z" fill="#fed843"/>
<path d="m184.84 393.596 22.26-22.26-22.66-43.81-22.265 22.265z" fill="#fabe2c"/>
<path d="m150.53 427.906-22.26 22.26-45.32-87.62 22.26-22.26z" fill="#fed843"/>
<path d="m128.27 450.166 22.26-22.26-22.655-43.815-22.26 22.26z" fill="#fabe2c"/>
<circle cx="15" cy="119.969" fill="#5ed8d3" r="15"/>
<circle cx="128" cy="199.969" fill="#d599ed" r="15"/>
<circle cx="192" cy="63.964" fill="#f66" r="15"/>
<circle cx="328" cy="415.967" fill="#31bebe" r="15"/>
<circle cx="440" cy="327.967" fill="#ad77e3" r="14.999"/>
</g>
</svg>
<text transform="scale(.1)" x="600.25" y="175" textLength="590.5" fill="#fff">
MAGIC BY
</text>
<text transform="scale(.1)" x="1400.75" y="175" textLength="700.5" fill="#fff" font-weight="bold">
SantaSpeen
</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 177 KiB

View File

@ -2,23 +2,17 @@
# Developed by Ahegao Devs # Developed by Ahegao Devs
# Written by: SantaSpeen # Written by: SantaSpeen
# Version 2.1 # Version 1.1
# Licence: MIT # Licence: MIT
# (c) ahegao.su 2022 # (c) ahegao.ovh 2022
import builtins import builtins
import logging import logging
import sys import sys
import traceback import traceback
import asyncio
from builtins import RecursionError from builtins import RecursionError
from typing import AnyStr from typing import AnyStr
try:
from aioconsole import ainput
except ImportError:
ainput = None
class ConsoleIO: class ConsoleIO:
@ -39,12 +33,11 @@ class ConsoleIO:
class Console: class Console:
def __init__(self, def __init__(self,
prompt_in=">", prompt_in: str = ">",
prompt_out="]:", prompt_out: str = "]:",
not_found="Command \"%s\" not found in alias.", not_found: str = "Command \"%s\" not found in alias.",
file=ConsoleIO, file: str or None = ConsoleIO,
debug=False, debug: bool = False) -> None:
async_loop=None) -> None:
""" """
def __init__(self, def __init__(self,
prompt_in: str = ">", prompt_in: str = ">",
@ -73,8 +66,6 @@ class Console:
self.is_run = False self.is_run = False
self.async_loop = async_loop
self.get_IO = ConsoleIO self.get_IO = ConsoleIO
def __debug(self, *x): def __debug(self, *x):
@ -87,14 +78,13 @@ class Console:
print(item) print(item)
@staticmethod def __get_max_len(self, arg) -> int:
def __get_max_len(arg) -> int:
i = 0 i = 0
arg = list(arg) arg = list(arg)
for a in arg: for a in arg:
ln = len(str(a)) l = len(str(a))
if ln > i: if l > i:
i = ln i = l
return i return i
def __create_man_message(self, argv: list) -> AnyStr: def __create_man_message(self, argv: list) -> AnyStr:
@ -111,7 +101,6 @@ class Console:
""" Print help message and alias of console commands""" """ Print help message and alias of console commands"""
self.__debug("creating help message") self.__debug("creating help message")
raw = False raw = False
max_len_v = 0
if "--raw" in argv: if "--raw" in argv:
max_len_v = self.__get_max_len(self.__alias.values()) max_len_v = self.__get_max_len(self.__alias.values())
print() print()
@ -125,15 +114,17 @@ class Console:
if not raw: if not raw:
message += f"%{max_len}s : Help message\n" % "Command" message += f"%{max_len}s : Help message\n" % "Command"
else: else:
message += f"%-{max_len - len(self.__prompt_out) - 1}s; %-{max_len_v}s; __doc__\n" % ("Key", "Object") message += f"%-{max_len - len(self.__prompt_out)-1}s; %-{max_len_v}s; __doc__\n" % ("Key", "Object")
for k, v in self.__alias.items(): for k, v in self.__alias.items():
doc = v['f'].__doc__ doc = v['f'].__doc__
if raw: if raw:
message += f"%-{max_len}s; %-{max_len_v}s; %s\n" % (k, v, doc)
message += f"%-{max_len}s; %-{max_len_v}s; %s\n" % (k, v, doc)
else: else:
if doc is None: if doc is None:
doc = " No help message found" doc = " No help message found"
message += f" %{max_len}s :%s\n" % (k, doc) message += f" %{max_len}s :%s\n" % (k, doc)
@ -215,14 +206,11 @@ class Console:
def emit(cls, record): def emit(cls, record):
try: try:
msg = cls.format(record) msg = cls.format(record)
if cls.stream.name == "<stderr>": ConsoleIO.write(self.__create_message(msg))
ConsoleIO.write(self.__create_message(msg))
else:
cls.stream.write(msg + cls.terminator)
cls.flush() cls.flush()
except RecursionError: except RecursionError:
raise raise
except Exception as e: except Exception:
cls.handleError(record) cls.handleError(record)
logging.StreamHandler.emit = emit logging.StreamHandler.emit = emit
@ -239,29 +227,6 @@ class Console:
builtins.print = self.__builtins_print builtins.print = self.__builtins_print
def _cli_logic(self, cmd_in):
try:
cmd = cmd_in.split(" ")[0]
if cmd == "":
pass
else:
command_object = self.__alias.get(cmd)
if command_object:
command = command_object['f']
if command_object['e']:
argv = cmd_in[len(cmd) + 1:].split(" ")
output = command(argv)
else:
output = command()
self.log(str(output))
else:
self.log(self.__not_found % cmd)
except Exception as e:
ConsoleIO.write_err("\rDuring the execution of the command, an error occurred:\n\n" +
str(traceback.format_exc()) +
"\nType Enter to continue.")
def run(self) -> None: def run(self) -> None:
""" """
def run(self) -> None: def run(self) -> None:
@ -278,31 +243,26 @@ class Console:
""" """
self.__debug(f"run while {whl}") self.__debug(f"run while {whl}")
while whl: while whl:
ConsoleIO.write("\r" + self.__prompt_in + " ") try:
self._cli_logic(ConsoleIO.read()) ConsoleIO.write("\r" + self.__prompt_in + " ")
cmd_in = ConsoleIO.read()
cmd = cmd_in.split(" ")[0]
if cmd == "":
pass
else:
command_object = self.__alias.get(cmd)
if command_object:
command = command_object['f']
if command_object['e']:
argv = cmd_in[len(cmd) + 1:].split(" ")
output = command(argv)
else:
output = command()
self.log(str(output))
async def async_run(self) -> None: else:
""" self.log(self.__not_found % cmd)
def async_run(self) -> None: except Exception as e:
:return: None ConsoleIO.write_err("\rDuring the execution of the command, an error occurred:\n\n" +
""" str(traceback.format_exc()) +
self.is_run = True "\nType Enter to continue.")
await self.async_run_while(True)
async def async_run_while(self, whl) -> None:
"""
async def async_run_while(self, whl) -> None:
:param whl: run while what?
:return: None
"""
if ainput is None:
print("Install aioconsole for async! pip install aioconsole")
exit(1)
if self.async_loop is None:
self.async_loop = asyncio.get_event_loop()
self.__debug(f"async run while {whl}")
reader = asyncio.StreamReader()
while whl:
ConsoleIO.write("\r" + self.__prompt_in + " ")
res = await ainput()
self._cli_logic(res)

View File

@ -6,8 +6,8 @@
# (c) ahegao.ovh 2022 # (c) ahegao.ovh 2022
from _typeshed import SupportsWrite from _typeshed import SupportsWrite
from asyncio import AbstractEventLoop from builtins import function
from typing import AnyStr, NoReturn from typing import AnyStr
class ConsoleIO: class ConsoleIO:
@ -29,8 +29,7 @@ class Console(object):
prompt_out: str = "]:", prompt_out: str = "]:",
not_found: str = "Command \"%s\" not found in alias.", not_found: str = "Command \"%s\" not found in alias.",
file: SupportsWrite[str] or None = Console, file: SupportsWrite[str] or None = Console,
debug: bool = False, debug: bool = False) -> None:
async_loop: AbstractEventLoop = None) -> NoReturn:
self.get_IO: ConsoleIO = ConsoleIO self.get_IO: ConsoleIO = ConsoleIO
self.is_run: bool = False self.is_run: bool = False
@ -39,13 +38,11 @@ class Console(object):
@property @property
def alias(self) -> dict: ... def alias(self) -> dict: ...
def add(self, key: str, func, argv: bool = False, man: str = "No have manual message") -> dict:... def add(self, key: str, func, argv: bool = False, man: str = "No have manual message") -> dict:...
def log(self, s: AnyStr, r='\r') -> NoReturn: ... def log(self, s: AnyStr, r='\r') -> None: ...
def __lshift__(self, s: AnyStr) -> NoReturn: def __lshift__(self, s: AnyStr) -> None:
self.write(s) self.write(s)
def write(self, s: AnyStr, r='\r') -> NoReturn: ... def write(self, s: AnyStr, r='\r') -> None: ...
def logger_hook(self) -> NoReturn: ... def logger_hook(self) -> None: ...
def builtins_hook(self) -> NoReturn: ... def builtins_hook(self) -> None: ...
def run(self) -> NoReturn: ... def run(self) -> None: ...
def run_while(self, whl) -> NoReturn:... def run_while(self, whl) -> None:...
async def async_run(self) -> NoReturn: ...
async def async_run_while(self, whl) -> NoReturn: ...