Source code for turbo_turtle.tests.test_wrappers

import copy
import argparse
from unittest.mock import patch

import pytest

from turbo_turtle import _abaqus_wrappers


command = "/dummy/command"

geometry_namespace_sparse = {
    "input_file": ["input_file"],
    "output_file": "output_file",
    "unit_conversion": 1.0,
    "euclidean_distance": 1.0,
    "planar": None,
    "model_name": "model_name",
    "part_name": [None],
    "delimiter": ",",
    "header_lines": 0,
    "revolution_angle": 360.0,
    "y_offset": 0.0,
    "rtol": None,
    "atol": None,
}
geometry_namespace_full = copy.deepcopy(geometry_namespace_sparse)
geometry_namespace_full.update({"planar": True, "part_name": ["part_name"], "rtol": 1.0e-9, "atol": 1.0e-9}),
geometry_expected_options_sparse = [
    "--input-file",
    "--output-file",
    "--unit-conversion",
    "--euclidean-distance",
    "--model-name",
    "--delimiter",
    "--header-lines",
    "--revolution-angle",
    "--y-offset",
]
geometry_unexpected_options_sparse = ["--planar", "--part-name", "--atol", "--rtol"]

cylinder_namespace = {
    "inner_radius": 1.0,
    "outer_radius": 2.0,
    "height": 1.0,
    "output_file": "output_file",
    "model_name": "model_name",
    "part_name": "part_name",
    "revolution_angle": 360.0,
    "y_offset": 0.0,
}
cylinder_expected_options = [
    command,
    "--inner-radius",
    "--outer-radius",
    "--height",
    "--output-file",
    "--model-name",
    "--part-name",
    "--revolution-angle",
    "--y-offset",
]

sphere_namespace_sparse = {
    "inner_radius": 1.0,
    "outer_radius": 2.0,
    "output_file": "output_file",
    "input_file": None,
    "quadrant": "both",
    "revolution_angle": 360.0,
    "y_offset": 0.0,
    "model_name": "model_name",
    "part_name": "part_name",
}
sphere_namespace_full = copy.deepcopy(sphere_namespace_sparse)
sphere_namespace_full.update({"input_file": "input_file"}),
sphere_expected_options_sparse = [
    command,
    "--inner-radius",
    "--outer-radius",
    "--output-file",
    "--quadrant",
    "--revolution-angle",
    "--y-offset",
    "--model-name",
    "--part-name",
]
sphere_unexpected_options_sparse = ["--input-file"]

partition_namespace_sparse = {
    "input_file": "input_file",
    "output_file": None,
    "center": (0.0, 0.0, 0.0),
    "xvector": (0.0, 0.0, 0.0),
    "zvector": (0.0, 0.0, 0.0),
    "model_name": "model_name",
    "part_name": ["part_name"],
    "big_number": 0.0,
}
partition_namespace_full = copy.deepcopy(partition_namespace_sparse)
partition_namespace_full.update({"output_file": "output_file"}),
partition_expected_options_sparse = [
    command,
    "--input-file",
    "--center",
    "--xvector",
    "--zvector",
    "--model-name",
    "--part-name",
    "--big-number",
]
partition_unexpected_options_sparse = ["--output-file"]

sets_namespace_sparse = {
    "input_file": "input_file",
    "output_file": None,
    "model_name": "model_name",
    "part_name": "part_name",
    "face_sets": None,
    "edge_sets": None,
    "vertex_sets": None,
}
sets_namespace_full = copy.deepcopy(sets_namespace_sparse)
sets_namespace_full.update(
    {
        "output_file": "output_file",
        "face_sets": [["name1", "2"]],
        "edge_sets": [["name2", "4"]],
        "vertex_sets": [["name3", "6"]],
    }
)
sets_expected_options_sparse = [command, "--input-file", "--model-name", "--part-name"]
sets_unexpected_options_sparse = ["--output-file", "--face-set", "--edge-set", "--vertex-set"]

mesh_namespace_sparse = {
    "input_file": "input_file",
    "element_type": "element_type",
    "output_file": None,
    "model_name": "model_name",
    "part_name": "part_name",
    "global_seed": "global_seed",
    "edge_seeds": None,
}
mesh_namespace_full = copy.deepcopy(mesh_namespace_sparse)
mesh_namespace_full.update({"output_file": "output_file", "edge_seeds": [["name", "1"]]}),
mesh_expected_options_sparse = [
    command,
    "--input-file",
    "--element-type",
    "--model-name",
    "--part-name",
    "--global-seed",
]
mesh_unexpected_options_sparse = ["--output-file", "--edge-seed"]

merge_namespace_sparse = {
    "input_file": ["input_file"],
    "output_file": "output_file",
    "merged_model_name": "merged_model_name",
    "model_name": [None],
    "part_name": [None],
}
merge_namespace_full = copy.deepcopy(merge_namespace_sparse)
merge_namespace_full.update(
    {
        "model_name": ["model_name"],
        "part_name": ["part_name"],
    }
),
merge_expected_options_sparse = [
    "--input-file",
    "--output-file",
    "--merged-model-name",
]
merge_unexpected_options_sparse = ["--model-name", "--part-name"]

export_namespace_sparse = {
    "input_file": "input_file",
    "model_name": "model_name",
    "part_name": ["part_name"],
    "element_type": [None],
    "destination": ".",
    "assembly": None,
}
export_namespace_full = copy.deepcopy(export_namespace_sparse)
export_namespace_full.update(
    {
        "element_type": ["element_type"],
        "assembly": True,
    }
),
export_expected_options_sparse = ["--input-file", "--model-name", "--part-name", "--destination"]
export_unexpected_options_sparse = ["--element-type", "--assembly"]

image_namespace_sparse = {
    "input_file": "input_file",
    "output_file": "output_file",
    "x_angle": 0.0,
    "y_angle": 0.0,
    "z_angle": 0.0,
    "image_size": [1, 2],
    "model_name": "model_name",
    "part_name": None,
    "color_map": "color_map",
}
image_namespace_full = copy.deepcopy(image_namespace_sparse)
image_namespace_full.update({"part_name": "part_name"}),
image_expected_options_sparse = [
    command,
    "--input-file",
    "--output-file",
    "--x-angle",
    "--y-angle",
    "--z-angle",
    "--image-size",
    "--model-name",
    "--color-map",
]
image_unexpected_options_sparse = ["--part-name"]

wrapper_tests = {
    "cylinder": ("cylinder", cylinder_namespace, cylinder_expected_options, []),
    "geometry: sparse": (
        "geometry",
        geometry_namespace_sparse,
        geometry_expected_options_sparse,
        geometry_unexpected_options_sparse,
    ),
    "geometry: full": (
        "geometry",
        geometry_namespace_full,
        geometry_expected_options_sparse + geometry_unexpected_options_sparse,
        [],
    ),
    "sphere: sparse": (
        "sphere",
        sphere_namespace_sparse,
        sphere_expected_options_sparse,
        sphere_unexpected_options_sparse,
    ),
    "sphere: full": (
        "sphere",
        sphere_namespace_full,
        sphere_expected_options_sparse + sphere_unexpected_options_sparse,
        [],
    ),
    "partition: sparse": (
        "partition",
        partition_namespace_sparse,
        partition_expected_options_sparse,
        partition_unexpected_options_sparse,
    ),
    "partition: full": (
        "partition",
        partition_namespace_full,
        partition_expected_options_sparse + partition_unexpected_options_sparse,
        [],
    ),
    "sets: sparse": (
        "sets",
        sets_namespace_sparse,
        sets_expected_options_sparse,
        sets_unexpected_options_sparse,
    ),
    "sets: full": (
        "sets",
        sets_namespace_full,
        sets_expected_options_sparse + sets_unexpected_options_sparse,
        [],
    ),
    "mesh: sparse": (
        "mesh",
        mesh_namespace_sparse,
        mesh_expected_options_sparse,
        mesh_unexpected_options_sparse,
    ),
    "mesh: full": (
        "mesh",
        mesh_namespace_full,
        mesh_expected_options_sparse + mesh_unexpected_options_sparse,
        [],
    ),
    "merge: sparse": (
        "merge",
        merge_namespace_sparse,
        merge_expected_options_sparse,
        merge_unexpected_options_sparse,
    ),
    "merge: full": (
        "merge",
        merge_namespace_full,
        merge_expected_options_sparse + merge_unexpected_options_sparse,
        [],
    ),
    "export: sparse": (
        "export",
        export_namespace_sparse,
        export_expected_options_sparse,
        export_unexpected_options_sparse,
    ),
    "export: full": (
        "export",
        export_namespace_full,
        export_expected_options_sparse + export_unexpected_options_sparse,
        [],
    ),
    "image: sparse": (
        "image",
        image_namespace_sparse,
        image_expected_options_sparse,
        image_unexpected_options_sparse,
    ),
    "image: full": (
        "image",
        image_namespace_full,
        image_expected_options_sparse + image_unexpected_options_sparse,
        [],
    ),
}


@pytest.mark.parametrize(
    "subcommand, namespace, expected_options, unexpected_options",
    wrapper_tests.values(),
    ids=wrapper_tests.keys(),
)
def test_abaqus_wrappers(subcommand, namespace, expected_options, unexpected_options):
    args = argparse.Namespace(**namespace)
    with patch("turbo_turtle._utilities.run_command") as mock_run:
        subcommand_wrapper = getattr(_abaqus_wrappers, subcommand)
        subcommand_wrapper(args, command)
    mock_run.assert_called_once()
    command_string = mock_run.call_args[0][0]
    for option in expected_options:
        assert option in command_string
    for option in unexpected_options:
        assert option not in command_string


[docs] def trim_namespace(original, pop_keys): """Create a modified dictionary deepcopy by removing the provided keys :returns: Modified dictionary deepcopy with pop keys removed :rtype: dict """ modified = copy.deepcopy(original) for key in pop_keys: if key in modified: modified.pop(key) return modified
def test_trim_namespace(): original = {"keep": "keep", "pop": "pop"} modified = trim_namespace(original, ("pop",)) assert modified == {"keep": "keep"} geometry_positional = ("input_file", "output_file") geometry_unused = ("model_name",) geometry_keywords = trim_namespace(geometry_namespace_sparse, geometry_positional + geometry_unused) cylinder_positional = ("inner_radius", "outer_radius", "height", "output_file") cylinder_unused = ("model_name",) cylinder_keywords = trim_namespace(cylinder_namespace, cylinder_positional + cylinder_unused) sphere_positional = ("inner_radius", "outer_radius", "output_file") sphere_unused = ("model_name",) sphere_keywords = trim_namespace(sphere_namespace_sparse, sphere_positional + sphere_unused) partition_positional = ("input_file",) partition_unused = ("model_name",) partition_keywords = trim_namespace(partition_namespace_sparse, partition_positional + partition_unused) mesh_positional = ("input_file", "element_type") mesh_unused = ("model_name",) mesh_keywords = trim_namespace(mesh_namespace_sparse, mesh_positional + mesh_unused) merge_positional = ("input_file", "output_file") merge_unused = ("model_name", "merged_model_name", "part_name") merge_keywords = trim_namespace(merge_namespace_sparse, merge_positional + merge_unused) export_namespace_cubit = copy.deepcopy(export_namespace_sparse) export_namespace_cubit["output_type"] = "output_type" export_positional = ("input_file",) export_unused = ("model_name", "assembly") export_keywords = trim_namespace(export_namespace_cubit, export_positional + export_unused) image_positional = ("input_file", "output_file", "command") image_unused = ("model_name", "part_name", "color_map") image_keywords = trim_namespace(image_namespace_sparse, image_positional + image_unused) cubit_wrapper_tests = { "geometry": ("geometry", geometry_namespace_sparse, (["input_file"], "output_file"), geometry_keywords), "cylinder": ("cylinder", cylinder_namespace, (1.0, 2.0, 1.0, "output_file"), cylinder_keywords), "sphere": ("sphere", sphere_namespace_sparse, (1.0, 2.0, "output_file"), sphere_keywords), "partition": ("partition", partition_namespace_sparse, ("input_file",), partition_keywords), "mesh": ("mesh", mesh_namespace_sparse, ("input_file", "element_type"), mesh_keywords), "merge": ("merge", merge_namespace_sparse, (["input_file"], "output_file"), merge_keywords), "export": ("export", export_namespace_cubit, ("input_file",), export_keywords), "image": ("image", image_namespace_sparse, ("input_file", "output_file", command), image_keywords), } @pytest.mark.parametrize( "subcommand, namespace, positional, keywords", cubit_wrapper_tests.values(), ids=cubit_wrapper_tests.keys(), ) def test_cubit_wrappers(subcommand, namespace, positional, keywords): args = argparse.Namespace(**namespace) with ( patch("turbo_turtle._utilities.import_cubit"), patch(f"turbo_turtle._cubit_python.{subcommand}") as mock_function, ): from turbo_turtle import _cubit_wrappers subcommand_wrapper = getattr(_cubit_wrappers, subcommand) subcommand_wrapper(args, command) mock_function.assert_called_once() call_positional = mock_function.call_args[0] call_keywords = mock_function.call_args[1] assert call_positional == positional assert call_keywords == keywords geometry_keywords = trim_namespace(geometry_namespace_sparse, geometry_positional) cylinder_keywords = trim_namespace(cylinder_namespace, cylinder_positional) sphere_keywords = trim_namespace(sphere_namespace_sparse, sphere_positional) partition_keywords = trim_namespace(partition_namespace_sparse, partition_positional) mesh_keywords = trim_namespace(mesh_namespace_sparse, mesh_positional) merge_keywords = trim_namespace(merge_namespace_sparse, merge_positional) export_keywords = trim_namespace(export_namespace_cubit, export_positional) image_keywords = trim_namespace(image_namespace_sparse, image_positional + image_unused) gmsh_wrapper_tests = { "geometry": ( "geometry", geometry_namespace_sparse, (["input_file"], "output_file"), geometry_keywords, ), "cylinder": ( "cylinder", cylinder_namespace, (1.0, 2.0, 1.0, "output_file"), cylinder_keywords, ), "sphere": ( "sphere", sphere_namespace_sparse, (1.0, 2.0, "output_file"), sphere_keywords, ), "partition": ( "partition", partition_namespace_sparse, ("input_file",), partition_keywords, ), "mesh": ( "mesh", mesh_namespace_sparse, ("input_file", "element_type"), mesh_keywords, ), "merge": ( "merge", merge_namespace_sparse, (["input_file"], "output_file"), merge_keywords, ), "export": ( "export", export_namespace_cubit, ("input_file",), export_keywords, ), "image": ( "image", image_namespace_sparse, ("input_file", "output_file"), image_keywords, ), } @pytest.mark.parametrize( "subcommand, namespace, positional, keywords", gmsh_wrapper_tests.values(), ids=gmsh_wrapper_tests.keys(), ) def test_gmsh_wrappers(subcommand, namespace, positional, keywords): args = argparse.Namespace(**namespace) implemented = ["geometry", "cylinder", "sphere", "mesh", "image"] if subcommand in implemented: with ( patch("turbo_turtle._utilities.import_gmsh"), patch(f"turbo_turtle._gmsh_python.{subcommand}") as mock_function, ): from turbo_turtle import _gmsh_wrappers subcommand_wrapper = getattr(_gmsh_wrappers, subcommand) subcommand_wrapper(args, command) mock_function.assert_called_once() call_positional = mock_function.call_args[0] call_keywords = mock_function.call_args[1] assert call_positional == positional assert call_keywords == keywords else: with ( patch("turbo_turtle._utilities.import_gmsh"), patch(f"turbo_turtle._gmsh_python.{subcommand}") as mock_function, pytest.raises(RuntimeError), ): from turbo_turtle import _gmsh_wrappers subcommand_wrapper = getattr(_gmsh_wrappers, subcommand) subcommand_wrapper(args, command)