Skip to content

Commit

Permalink
Fix Asych io + Status handler
Browse files Browse the repository at this point in the history
  • Loading branch information
lassebje committed Dec 13, 2023
1 parent 2e73f37 commit 47139ef
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 18 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

setup(
name="simapy",
version="4.6.0",
version="4.6.1.dev0",
author="SINTEF Ocean",
description="Python utilities for SIMA",
url="https://github.com/SINTEF/simapy",
Expand Down
50 changes: 33 additions & 17 deletions src/simapy/sre.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,55 @@
"""Run a command using SIMA runtime engine (sre executable)"""
import asyncio
import os
import re
from pathlib import Path
from typing import Sequence
from typing import Sequence,Callable
from simapy.sima_writer import SIMAWriter


async def run_command(args, error_file, out_file):
async def run_command(args, error_file, out_file, status_handler):
""""Run a command asynchronously and print output to standard out.
Standard err is piped to stderr.txt in the working directory"""
process = await asyncio.create_subprocess_exec(
*args, stdout=asyncio.subprocess.PIPE, stderr=error_file
)

while True:
stdout, _ = await process.communicate()

if stdout:
for line in stdout.splitlines():
sline = line.decode("utf-8")
if sline.startswith("@STATUS"):
print("STATUS found:" + sline, end="\n")
else:
print(sline, end="\n")
print(sline, end="\n", file=out_file)

if process.returncode is not None:
return process.returncode

# Use an awaitable to read data from stdout
# Read the next line of data from stdout asynchronously
data = await process.stdout.readline()
if not data:
break # Break the loop when there's no more data
sline = data.decode('utf-8')
if status_handler and sline.startswith("@STATUS"):
__parse_status(sline,status_handler)
else:
print(sline, end="\n")
print(sline, end="\n", file=out_file)

# Wait for the subprocess to finish
await process.wait()
if process.returncode is not None:
return process.returncode

def __parse_status(line: str,status_handler):
# A status line looks like this: @STATUS "Total" 100 1000
# The first number is the current value, the second is the total
pattern = r'@STATUS "(?P<label>\w+)" (?P<current>\d+) (?P<total>\d+)'
# Match the pattern in the string
match = re.match(pattern, line)
if match:
label = match.group('label')
current = int(match.group('current'))
total = int(match.group('total'))
status_handler(label,current,total)

class SIMA:
""""Run a command using SIMA runtime engine (sre executable)"""

def __init__(self, exe=None, fail_on_error=True):
self.fail_on_error = fail_on_error
self.status_handler: Callable = None
if exe:
self.exe = exe
else:
Expand All @@ -59,7 +75,7 @@ def run(self, working_dir, command_args: Sequence[str]):
with open(err_file, "w", encoding="utf8") as e_f, open(
out_file, "w", encoding="utf8"
) as o_f:
exit_code = asyncio.run(run_command(arguments, e_f, o_f))
exit_code = asyncio.run(run_command(arguments, e_f, o_f, self.status_handler))
if exit_code != 0 and self.fail_on_error:
raise RuntimeError(f"SIMA exited with error code {exit_code}")

Expand Down

0 comments on commit 47139ef

Please sign in to comment.