diff --git a/src/bedit_gui/__main__.py b/src/bedit_gui/__main__.py new file mode 100644 index 0000000..58367d9 --- /dev/null +++ b/src/bedit_gui/__main__.py @@ -0,0 +1,5 @@ +def main(): + pass + +if __name__ == "__name__": + raise SystemExit(main()) \ No newline at end of file diff --git a/src/bedit_simulation/simulation.py b/src/bedit_simulation/simulation.py index d6f3d6c..8203a26 100644 --- a/src/bedit_simulation/simulation.py +++ b/src/bedit_simulation/simulation.py @@ -54,7 +54,7 @@ class ModelCheckResult: model_name: str successful: bool - output: str + output: list[str] errors: str @@ -280,7 +280,7 @@ class Simulation: return ModelCheckResult( model_name=model_name, successful="completed successfully" in process.stdout.lower(), - output=process.stdout, + output=_decode_omc_strings(process.stdout), errors=process.stderr, ) @@ -689,3 +689,52 @@ def _load_model_script( "", ] ) + + +def _decode_omc_strings(output: str) -> list[str]: + """Decode OMC strings, including quoted values spanning several lines.""" + decoded: list[str] = [] + quoted_lines: list[str] = [] + + for line in output.splitlines(): + if quoted_lines: + quoted_lines.append(line) + if _ends_with_unescaped_quote(line): + decoded.extend(_decode_quoted_lines(quoted_lines)) + quoted_lines = [] + continue + + if line.startswith('"') and not _ends_with_unescaped_quote(line[1:]): + quoted_lines.append(line) + continue + + try: + value = json.loads(line) + except json.JSONDecodeError: + decoded.append(line) + else: + if isinstance(value, str): + decoded.extend(value.splitlines() or [""]) + else: + decoded.append(line) + + if quoted_lines: + decoded.extend(_decode_quoted_lines(quoted_lines)) + return decoded + + +def _ends_with_unescaped_quote(value: str) -> bool: + if not value.endswith('"'): + return False + before_quote = value[:-1] + backslashes = len(before_quote) - len(before_quote.rstrip("\\")) + return backslashes % 2 == 0 + + +def _decode_quoted_lines(lines: Sequence[str]) -> list[str]: + value = "\n".join(lines) + try: + decoded = json.loads(value.replace("\n", "\\n")) + except json.JSONDecodeError: + decoded = value.removeprefix('"').removesuffix('"') + return decoded.splitlines() or [""] diff --git a/src/bedit_util/simulate.py b/src/bedit_util/simulate.py index 9e146d7..9d84b4e 100644 --- a/src/bedit_util/simulate.py +++ b/src/bedit_util/simulate.py @@ -37,6 +37,10 @@ async def run_simulation( runner = OpenModelicaRunner(omc_command, timeout=timeout) simulation = Simulation(runner) await simulation.load(component) + check = await simulation.check() + for line in check.output: + if line and line not in ['""', 'true', 'false']: + print(line) if working_directory is not None: await simulation.build(working_directory) return await _run_with_progress( @@ -45,7 +49,7 @@ async def run_simulation( progress_callback, ) with tempfile.TemporaryDirectory(prefix="bedit-simulation-") as temporary: - await simulation.build(temporary) + build = await simulation.build(temporary) result = await _run_with_progress( simulation, options, diff --git a/tests/unit/test_simulation.py b/tests/unit/test_simulation.py index c1f39a1..a358181 100644 --- a/tests/unit/test_simulation.py +++ b/tests/unit/test_simulation.py @@ -45,7 +45,9 @@ def _fake_omc( return ProcessResult( tuple(command), 0, - '"Check of Example completed successfully."\n', + '"Check of Example completed successfully.\n' + 'Class Example has 1 equation(s) and 1 variable(s)."\n' + '""\n', "", ) @@ -114,6 +116,11 @@ def test_checks_existing_modelica_source(tmp_path: Path) -> None: result = asyncio.run(check()) assert result.successful + assert result.output == [ + "Check of Example completed successfully.", + "Class Example has 1 equation(s) and 1 variable(s).", + "", + ] script = (tmp_path / "model-command.mos").read_text(encoding="utf-8") assert "checkModel(Example);" in script