dev
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/.idea/
|
||||||
|
**/__pycache__/
|
||||||
|
/tests/
|
||||||
1
README.md
Normal file
1
README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[nekomata is now in early-dev state](https://nekomata.kotikot.com/)
|
||||||
4
neko_run_controller_asyncio/__init__.py
Normal file
4
neko_run_controller_asyncio/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from . import modules
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [modules]
|
||||||
0
neko_run_controller_asyncio/modules/__init__.py
Normal file
0
neko_run_controller_asyncio/modules/__init__.py
Normal file
37
neko_run_controller_asyncio/modules/controller.py
Normal file
37
neko_run_controller_asyncio/modules/controller.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import asyncio
|
||||||
|
from asyncio import subprocess
|
||||||
|
import psutil
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
|
def kill(proc_pid):
|
||||||
|
try:
|
||||||
|
process = psutil.Process(proc_pid)
|
||||||
|
for proc in process.children(recursive=True):
|
||||||
|
proc.kill()
|
||||||
|
process.kill()
|
||||||
|
except psutil.NoSuchProcess:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
async def run_process(
|
||||||
|
command: str, env: dict,
|
||||||
|
try_to_fix_flush: bool = True
|
||||||
|
) -> subprocess.Process:
|
||||||
|
process = await subprocess.create_subprocess_shell(
|
||||||
|
cmd=command,
|
||||||
|
env=env | {"PYTHONUNBUFFERED": "1"} if try_to_fix_flush else env,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
|
||||||
|
return process
|
||||||
|
|
||||||
|
|
||||||
|
async def stream_handler(stream: asyncio.streams.StreamReader, real_handler: Callable):
|
||||||
|
while True:
|
||||||
|
line = (await stream.readline()).decode().strip()
|
||||||
|
if not line:
|
||||||
|
return
|
||||||
|
await real_handler(line)
|
||||||
2
neko_run_controller_asyncio/modules/default_handlers.py
Normal file
2
neko_run_controller_asyncio/modules/default_handlers.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
async def log_handler(line: str):
|
||||||
|
print(line)
|
||||||
2
neko_run_controller_asyncio/neko/__init__.py
Normal file
2
neko_run_controller_asyncio/neko/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from .interfaces import RunControllerHandlersInterface
|
||||||
|
from .types import CommandRunner
|
||||||
23
neko_run_controller_asyncio/neko/interfaces.py
Normal file
23
neko_run_controller_asyncio/neko/interfaces.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from neko_run_controller_std.neko.types import LogsHandler
|
||||||
|
from typing import Type
|
||||||
|
import dataclasses
|
||||||
|
|
||||||
|
from neko_run_controller_std.neko.interfaces import RunControllerHandlersInterface
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class __HiddenStorage:
|
||||||
|
logs_handlers: list[Type[LogsHandler]] = dataclasses.field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
_storage = __HiddenStorage()
|
||||||
|
|
||||||
|
|
||||||
|
class RRunControllerHandlersInterface(RunControllerHandlersInterface):
|
||||||
|
@staticmethod
|
||||||
|
def add_logs_handler(handler: Type[LogsHandler]):
|
||||||
|
_storage.logs_handlers.append(handler)
|
||||||
|
|
||||||
|
|
||||||
|
RunControllerHandlersInterface = RRunControllerHandlersInterface
|
||||||
|
__all__ = [RunControllerHandlersInterface]
|
||||||
61
neko_run_controller_asyncio/neko/types.py
Normal file
61
neko_run_controller_asyncio/neko/types.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from neko_run_controller_std.neko.types import CommandRunner, LogsHandler
|
||||||
|
from ..modules.controller import run_process, stream_handler, kill
|
||||||
|
import os
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
from .interfaces import _storage
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
|
class RCommandRunner(CommandRunner):
|
||||||
|
def __init__(self, name: str, command: str, env: dict = None, chdir: str = None):
|
||||||
|
self.name = name
|
||||||
|
self.command = command
|
||||||
|
self.env = env
|
||||||
|
self.chdir = chdir
|
||||||
|
self.pid = None
|
||||||
|
|
||||||
|
if not env:
|
||||||
|
self.env = dict(os.environ)
|
||||||
|
|
||||||
|
async def __start(self):
|
||||||
|
__start_dir = os.getcwd()
|
||||||
|
if self.chdir:
|
||||||
|
os.chdir(self.chdir)
|
||||||
|
self.process = await run_process(
|
||||||
|
command=self.command,
|
||||||
|
env=self.env,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.__log_tasks = list()
|
||||||
|
for handler_builder in _storage.logs_handlers:
|
||||||
|
handler = handler_builder(runner=self)
|
||||||
|
|
||||||
|
self.__log_tasks.append(
|
||||||
|
asyncio.create_task(stream_handler(self.process.stdout, handler.stdout))
|
||||||
|
)
|
||||||
|
self.__log_tasks.append(
|
||||||
|
asyncio.create_task(stream_handler(self.process.stderr, handler.stderr))
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pid = self.process.pid
|
||||||
|
|
||||||
|
async def wait(self):
|
||||||
|
await self.process.wait()
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
await self.__start()
|
||||||
|
|
||||||
|
async def kill(self):
|
||||||
|
if not self.pid:
|
||||||
|
warnings.warn('Process is not started', RuntimeWarning)
|
||||||
|
return
|
||||||
|
[task.cancel() for task in self.__log_tasks]
|
||||||
|
kill(self.pid)
|
||||||
|
await self.process.wait()
|
||||||
|
|
||||||
|
|
||||||
|
CommandRunner = RCommandRunner
|
||||||
|
__all__ = [CommandRunner, LogsHandler]
|
||||||
47
poetry.lock
generated
Normal file
47
poetry.lock
generated
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "neko-run-controller-std"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
optional = false
|
||||||
|
python-versions = "^3.11"
|
||||||
|
files = []
|
||||||
|
develop = true
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "directory"
|
||||||
|
url = "../neko-run-controller-std"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psutil"
|
||||||
|
version = "5.9.8"
|
||||||
|
description = "Cross-platform lib for process and system monitoring in Python."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||||
|
files = [
|
||||||
|
{file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"},
|
||||||
|
{file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"},
|
||||||
|
{file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"},
|
||||||
|
{file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"},
|
||||||
|
{file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"},
|
||||||
|
{file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"},
|
||||||
|
{file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"},
|
||||||
|
{file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"},
|
||||||
|
{file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"},
|
||||||
|
{file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"},
|
||||||
|
{file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"},
|
||||||
|
{file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"},
|
||||||
|
{file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"},
|
||||||
|
{file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"},
|
||||||
|
{file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"},
|
||||||
|
{file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "2.0"
|
||||||
|
python-versions = "^3.11"
|
||||||
|
content-hash = "6839aa94726d7cae42726a68d0335068e86fa469a418ca7286a8bba122496d4f"
|
||||||
19
pyproject.toml
Normal file
19
pyproject.toml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[tool.poetry]
|
||||||
|
name = "neko-run-controller-asyncio"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
authors = ["hhh <h@localhost>"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.11"
|
||||||
|
psutil = "^5.9.8"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.poetry.group.neko.dependencies]
|
||||||
|
neko-run-controller-std = {path = "../neko-run-controller-std", develop = true}
|
||||||
|
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
Reference in New Issue
Block a user