chore: bump zhurnal version to 0.2.0 and fix dependency specifier spacing in requires.txt
All checks were successful
Build and test Zhurnal / Test (push) Successful in 1m18s

This commit is contained in:
bot 2026-06-14 15:24:16 +00:00
parent a885ad9e02
commit 02ce6c5c64
5 changed files with 26 additions and 20 deletions

BIN
dist/zhurnal-0.2.0-py3-none-any.whl vendored Normal file

Binary file not shown.

BIN
dist/zhurnal-0.2.0.tar.gz vendored Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: zhurnal
Version: 0.1.0
Version: 0.2.0
Summary: Process monitoring and management web application
Author: retoor
Author-email: retoor@molodetz.nl
@ -8,7 +8,7 @@ Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: aiohttp
Requires-Dist: setuptools
Requires-Dist: app@ git+https://retoor.molodetz.nl/retoor/app.git
Requires-Dist: app @ git+https://retoor.molodetz.nl/retoor/app.git
# Zhurnal: Real-Time Process Monitoring Web Interface 🚀

View File

@ -1,3 +1,3 @@
aiohttp
setuptools
app@ git+https://retoor.molodetz.nl/retoor/app.git
app @ git+https://retoor.molodetz.nl/retoor/app.git

View File

@ -209,15 +209,15 @@ class Zhurnal(BaseApplication):
self.process_tasks = {}
self.shutdown_event = asyncio.Event()
super().__init__(*args, **kwargs)
# Register signal handlers for graceful shutdown
loop = asyncio.get_event_loop()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, self.handle_exit)
self.on_startup.append(self.start_processes)
self.on_cleanup.append(self.cleanup_processes)
self.clients = []
self.router.add_get("/ws", self.websocket_handler)
self.router.add_get("/", self.index_handler)
@ -231,12 +231,12 @@ class Zhurnal(BaseApplication):
async def cleanup_processes(self, app):
"""Cleanup all running subprocesses."""
log.info("Cleaning up processes...")
# Terminate all running processes
for command, process_info in list(self.processes.items()):
try:
# Get the subprocess
process = process_info.get('process')
process = process_info.get("process")
if process and process.returncode is None:
log.info(f"Terminating process: {command}")
try:
@ -250,7 +250,7 @@ class Zhurnal(BaseApplication):
process.kill()
except Exception as e:
log.error(f"Error cleaning up process {command}: {e}")
# Cancel any running tasks
for task in list(self.process_tasks.values()):
if not task.done():
@ -297,13 +297,10 @@ class Zhurnal(BaseApplication):
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
)
# Store process information
self.processes[command] = {
'process': process,
'name': process_name
}
self.processes[command] = {"process": process, "name": process_name}
log.info(f"Running process {process_name}: {command}")
async def read_output(app, name, process, f, is_stderr=False):
@ -313,15 +310,17 @@ class Zhurnal(BaseApplication):
# Check if shutdown is requested
if self.shutdown_event.is_set():
break
time_current = time.time()
time_elapsed = round(
time_previous and time_current - time_previous or 0, 4
)
decoded_line = line.decode("utf-8", "ignore").strip()
print(decoded_line)
decoded_line = "".join(c for c in decoded_line if c.isprintable())
decoded_line = "".join(
c for c in decoded_line if c.isprintable()
)
# Broadcast to all WebSocket clients
for client in app.clients:
await client.send_str(
@ -346,7 +345,13 @@ class Zhurnal(BaseApplication):
# Read stdout and stderr concurrently
await asyncio.gather(
read_output(self, f"{process_name}:stdout", process, process.stdout),
read_output(self, f"{process_name}:stderr", process, process.stderr, is_stderr=True)
read_output(
self,
f"{process_name}:stderr",
process,
process.stderr,
is_stderr=True,
),
)
# Wait for process to complete
@ -361,7 +366,7 @@ class Zhurnal(BaseApplication):
log.error(
f"Process {process_name}:{command} exited with non-zero status {process.returncode}."
)
except Exception as e:
log.error(f"Error running process {process_name}: {e}")
finally:
@ -422,5 +427,6 @@ def cli():
app.run(host=args.host, port=args.port)
if __name__ == "__main__":
cli()