From 57bb251cccf807e28ac21155f50a6a206f92ac69 Mon Sep 17 00:00:00 2001 From: sverhoeven Date: Mon, 2 Oct 2023 12:06:57 +0200 Subject: [PATCH] Switch to 2 arg constructor + Add tests for julia --- grpc4bmi/bmi_julia_model.py | 18 +++++----- test/test_julia.py | 67 +++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 test/test_julia.py diff --git a/grpc4bmi/bmi_julia_model.py b/grpc4bmi/bmi_julia_model.py index 94b02b6..39d1339 100644 --- a/grpc4bmi/bmi_julia_model.py +++ b/grpc4bmi/bmi_julia_model.py @@ -18,17 +18,19 @@ class BmiJulia(Bmi): BasicModelInterface is available in https://github.com/Deltares/BasicModelInterface.jl repo. Args: - package: Name of Julia package which contains interface and model classes - implementation_name: Name of Julia variable which implements BasicModelInterface model_name: Name of Julia model class + implementation_name: Name of Julia variable which implements BasicModelInterface """ - def __init__(self, package, implementation_name, model_name): - self.module = package - self.model_name = model_name - jl.seval("using " + package) - self.model = getattr(getattr(jl, self.module), self.model_name) - self.implementation = getattr(getattr(jl, package), implementation_name) + state = None + + def __init__(self, model_name, implementation_name = 'BasicModelInterface'): + package4model = model_name.split('.')[0] + package4implementation = implementation_name.split('.')[0] + jl.seval("import " + package4model) + jl.seval("import " + package4implementation) + self.model = jl.seval(model_name) + self.implementation = jl.seval(implementation_name) def initialize(self, config_file: str) -> None: """Perform startup tasks for the model. diff --git a/test/test_julia.py b/test/test_julia.py new file mode 100644 index 0000000..a4ee125 --- /dev/null +++ b/test/test_julia.py @@ -0,0 +1,67 @@ +from pathlib import Path +from textwrap import dedent +import numpy as np +import pytest + +try: + from grpc4bmi.bmi_julia_model import install, BmiJulia + from juliacall import Main as jl +except ImportError: + BmiJulia = None + + +@pytest.mark.skipif(not BmiJulia, reason="R and its dependencies are not installed") +@pytest.fixture(scope="module") +def install_heat(): + jl.Pkg.add( + url="https://github.com/csdms/bmi-example-julia.git", + rev="d8b354ceddf6b048727c2e214031f43d62964120", + ) + + +@pytest.mark.skipif(not BmiJulia, reason="R and its dependencies are not installed") +class TestFakeFailingModel: + @pytest.fixture + def cfg_file(self, tmp_path: Path): + fn = tmp_path / "heat.toml" + fn.write_text( + dedent( + """\ + # Heat model configuration + shape = [6, 8] + spacing = [1.0, 1.0] + origin = [0.0, 0.0] + alpha = 1.0 + """ + ) + ) + return fn + + @pytest.fixture + def model(self, cfg_file): + model = BmiJulia("Heat.Model") + model.initialize(str(cfg_file)) + return model + + @pytest.mark.parametrize( + "fn_name,fn_args,expected", + [ + ("get_component_name", tuple(), "The 2D Heat Equation"), + ('get_input_item_count', tuple(), 1), + ('get_output_item_count', tuple(), 1), + ('get_input_var_names', tuple(), ['plate_surface__temperature']), + ('get_output_var_names', tuple(), ['plate_surface__temperature']), + ('get_start_time', tuple(), 0.0), + ('get_end_time', tuple(), np.Inf), + ('get_time_step', tuple(), 0.25), + ('get_time_units', tuple(), 's'), + ], + ) + def test_methods(self, model: BmiJulia, fn_name, fn_args, expected): + fn = getattr(model, fn_name) + if fn_args == tuple(): + result = fn() + else: + result = fn(*fn_args) + # TODO almost equal + assert result == expected