diff --git a/src/moldflow/boundary_conditions.py b/src/moldflow/boundary_conditions.py index e01bb13..92c28da 100644 --- a/src/moldflow/boundary_conditions.py +++ b/src/moldflow/boundary_conditions.py @@ -6,9 +6,8 @@ BoundaryConditions Class API Wrapper """ -from .helper import coerce_optional_dispatch from .common import LogMessage, AnalysisType, ConstraintType -from .helper import check_type, get_enum_value +from .helper import check_type, check_and_coerce_optional, get_enum_value from .com_proxy import safe_com from .logger import process_log from .ent_list import EntList @@ -76,11 +75,10 @@ def create_fixed_constraints(self, nodes: EntList | None, analysis: AnalysisType int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_fixed_constraints") - if nodes is not None: - check_type(nodes, EntList) + analysis = get_enum_value(analysis, AnalysisType) return self.boundary_conditions.CreateFixedConstraints( - coerce_optional_dispatch(nodes, "ent_list"), analysis + check_and_coerce_optional(nodes, EntList), analysis ) def create_core_shift_fixed_constraints( @@ -97,11 +95,10 @@ def create_core_shift_fixed_constraints( int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_fixed_constraints") - if nodes is not None: - check_type(nodes, EntList) + check_type(retract_time, (float, int)) return self.boundary_conditions.CreateFixedConstraints2( - coerce_optional_dispatch(nodes, "ent_list"), retract_time + check_and_coerce_optional(nodes, EntList), retract_time ) def create_pin_constraints(self, nodes: EntList | None, analysis: AnalysisType | int) -> int: @@ -116,11 +113,10 @@ def create_pin_constraints(self, nodes: EntList | None, analysis: AnalysisType | int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_pin_constraints") - if nodes is not None: - check_type(nodes, EntList) + analysis = get_enum_value(analysis, AnalysisType) return self.boundary_conditions.CreatePinConstraints( - coerce_optional_dispatch(nodes, "ent_list"), analysis + check_and_coerce_optional(nodes, EntList), analysis ) def create_core_shift_pin_constraints( @@ -137,11 +133,10 @@ def create_core_shift_pin_constraints( int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_pin_constraints") - if nodes is not None: - check_type(nodes, EntList) + check_type(retract_time, (float, int)) return self.boundary_conditions.CreatePinConstraints2( - coerce_optional_dispatch(nodes, "ent_list"), retract_time + check_and_coerce_optional(nodes, EntList), retract_time ) # pylint: disable-next=R0913,R0917 @@ -165,18 +160,14 @@ def create_spring_constraints( int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_spring_constraints") - if nodes is not None: - check_type(nodes, EntList) + analysis = get_enum_value(analysis, AnalysisType) - if trans is not None: - check_type(trans, Vector) - if rotation is not None: - check_type(rotation, Vector) + return self.boundary_conditions.CreateSpringConstraints( - coerce_optional_dispatch(nodes, "ent_list"), + check_and_coerce_optional(nodes, EntList), analysis, - coerce_optional_dispatch(trans, "vector"), - coerce_optional_dispatch(rotation, "vector"), + check_and_coerce_optional(trans, Vector), + check_and_coerce_optional(rotation, Vector), ) # pylint: disable-next=R0913,R0917 @@ -200,17 +191,12 @@ def create_core_shift_spring_constraints( int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_spring_constraints") - if nodes is not None: - check_type(nodes, EntList) - if trans is not None: - check_type(trans, Vector) - if rotation is not None: - check_type(rotation, Vector) + check_type(retract_time, (float, int)) return self.boundary_conditions.CreateSpringConstraints2( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(trans, "vector"), - coerce_optional_dispatch(rotation, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(trans, Vector), + check_and_coerce_optional(rotation, Vector), retract_time, ) @@ -239,27 +225,18 @@ def create_general_constraints( int: Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_general_constraints") - if nodes is not None: - check_type(nodes, EntList) - if trans is not None: - check_type(trans, Vector) - if rotation is not None: - check_type(rotation, Vector) - if trans_types is not None: - check_type(trans_types, Vector) - if rotation_types is not None: - check_type(rotation_types, Vector) + analysis = get_enum_value(analysis, AnalysisType) trans_types = self._check_vector(trans_types) rotation_types = self._check_vector(rotation_types) return self.boundary_conditions.CreateGeneralConstraints2( - coerce_optional_dispatch(nodes, "ent_list"), + check_and_coerce_optional(nodes, EntList), analysis, - coerce_optional_dispatch(trans, "vector"), - coerce_optional_dispatch(rotation, "vector"), - coerce_optional_dispatch(trans_types, "vector"), - coerce_optional_dispatch(rotation_types, "vector"), + check_and_coerce_optional(trans, Vector), + check_and_coerce_optional(rotation, Vector), + check_and_coerce_optional(trans_types, Vector), + check_and_coerce_optional(rotation_types, Vector), ) # pylint: disable-next=R0913,R0917 @@ -292,25 +269,16 @@ def create_core_shift_general_constraints( locals(), name="create_core_shift_general_constraints", ) - if nodes is not None: - check_type(nodes, EntList) - if trans is not None: - check_type(trans, Vector) - if rotation is not None: - check_type(rotation, Vector) - if trans_types is not None: - check_type(trans_types, Vector) - if rotation_types is not None: - check_type(rotation_types, Vector) + check_type(retract_time, (int, float)) trans_types = self._check_vector(trans_types) rotation_types = self._check_vector(rotation_types) return self.boundary_conditions.CreateGeneralConstraints3( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(trans, "vector"), - coerce_optional_dispatch(rotation, "vector"), - coerce_optional_dispatch(trans_types, "vector"), - coerce_optional_dispatch(rotation_types, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(trans, Vector), + check_and_coerce_optional(rotation, Vector), + check_and_coerce_optional(trans_types, Vector), + check_and_coerce_optional(rotation_types, Vector), retract_time, ) @@ -329,16 +297,11 @@ def create_nodal_loads( int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_nodal_loads") - if nodes is not None: - check_type(nodes, EntList) - if force is not None: - check_type(force, Vector) - if moment is not None: - check_type(moment, Vector) + return self.boundary_conditions.CreateNodalLoads( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(force, "vector"), - coerce_optional_dispatch(moment, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(force, Vector), + check_and_coerce_optional(moment, Vector), ) def create_edge_loads(self, nodes: EntList | None, force: Vector | None) -> int: @@ -353,12 +316,9 @@ def create_edge_loads(self, nodes: EntList | None, force: Vector | None) -> int: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_edge_loads") - if nodes is not None: - check_type(nodes, EntList) - if force is not None: - check_type(force, Vector) + return self.boundary_conditions.CreateEdgeLoads( - coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(force, "vector") + check_and_coerce_optional(nodes, EntList), check_and_coerce_optional(force, Vector) ) def create_elemental_loads(self, tri: EntList | None, force: Vector | None) -> int: @@ -373,12 +333,9 @@ def create_elemental_loads(self, tri: EntList | None, force: Vector | None) -> i int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_elemental_loads") - if tri is not None: - check_type(tri, EntList) - if force is not None: - check_type(force, Vector) + return self.boundary_conditions.CreateElementalLoads( - coerce_optional_dispatch(tri, "ent_list"), coerce_optional_dispatch(force, "vector") + check_and_coerce_optional(tri, EntList), check_and_coerce_optional(force, Vector) ) def create_pressure_loads(self, tri: EntList | None, pressure: float) -> int: @@ -393,11 +350,10 @@ def create_pressure_loads(self, tri: EntList | None, pressure: float) -> int: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_pressure_loads") - if tri is not None: - check_type(tri, EntList) + check_type(pressure, (float, int)) return self.boundary_conditions.CreatePressureLoads( - coerce_optional_dispatch(tri, "ent_list"), pressure + check_and_coerce_optional(tri, EntList), pressure ) def create_temperature_loads(self, tri: EntList | None, top: float, bottom: float) -> int: @@ -413,12 +369,11 @@ def create_temperature_loads(self, tri: EntList | None, top: float, bottom: floa int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_temperature_loads") - if tri is not None: - check_type(tri, EntList) + check_type(top, (float, int)) check_type(bottom, (float, int)) return self.boundary_conditions.CreateTemperatureLoads( - coerce_optional_dispatch(tri, "ent_list"), top, bottom + check_and_coerce_optional(tri, EntList), top, bottom ) def create_volume_loads(self, tri: EntList | None, force: Vector | None) -> int: @@ -433,12 +388,9 @@ def create_volume_loads(self, tri: EntList | None, force: Vector | None) -> int: int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_volume_loads") - if tri is not None: - check_type(tri, EntList) - if force is not None: - check_type(force, Vector) + return self.boundary_conditions.CreateVolumeLoads( - coerce_optional_dispatch(tri, "ent_list"), coerce_optional_dispatch(force, "vector") + check_and_coerce_optional(tri, EntList), check_and_coerce_optional(force, Vector) ) def create_critical_dimension( @@ -457,15 +409,12 @@ def create_critical_dimension( int: Number of loads created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_critical_dimension") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) + check_type(upper, (float, int)) check_type(lower, (float, int)) return self.boundary_conditions.CreateCriticalDimension( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), upper, lower, ) @@ -487,14 +436,11 @@ def create_doe_critical_dimension( process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="create_doe_critical_dimension" ) - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) + check_type(name, str) return self.boundary_conditions.CreateDoeCriticalDimension( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), name, ) @@ -516,17 +462,13 @@ def create_ndbc( EntList: The list of NDBC that were created. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_ndbc") - if nodes is not None: - check_type(nodes, EntList) - if normal is not None: - check_type(normal, Vector) + check_type(prop_type, int) - if prop is not None: - check_type(prop, Property) - prop_disp = coerce_optional_dispatch(prop, "prop") + + prop_disp = check_and_coerce_optional(prop, Property) result = self.boundary_conditions.CreateNDBC( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(normal, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(normal, Vector), prop_type, prop_disp, ) @@ -552,17 +494,13 @@ def create_ndbc_at_xyz( EntList: The list of NDBC that were created. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_ndbc_at_xyz") - if coord is not None: - check_type(coord, Vector) - if normal is not None: - check_type(normal, Vector) + check_type(prop_type, int) - if prop is not None: - check_type(prop, Property) - prop_disp = coerce_optional_dispatch(prop, "prop") + + prop_disp = check_and_coerce_optional(prop, Property) result = self.boundary_conditions.CreateNDBCAtXYZ( - coerce_optional_dispatch(coord, "vector"), - coerce_optional_dispatch(normal, "vector"), + check_and_coerce_optional(coord, Vector), + check_and_coerce_optional(normal, Vector), prop_type, prop_disp, ) @@ -583,16 +521,11 @@ def move_ndbc(self, ndbc: EntList | None, nodes: EntList | None, normal: Vector bool: True if the NDBC was moved successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_ndbc") - if ndbc is not None: - check_type(ndbc, EntList) - if nodes is not None: - check_type(nodes, EntList) - if normal is not None: - check_type(normal, Vector) + return self.boundary_conditions.MoveNDBC( - coerce_optional_dispatch(ndbc, "ent_list"), - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(normal, "vector"), + check_and_coerce_optional(ndbc, EntList), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(normal, Vector), ) def move_ndbc_to_xyz( @@ -610,16 +543,11 @@ def move_ndbc_to_xyz( bool: True if successful; False if not """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_ndbc_to_xyz") - if ndbc is not None: - check_type(ndbc, EntList) - if coord is not None: - check_type(coord, Vector) - if normal is not None: - check_type(normal, Vector) + return self.boundary_conditions.MoveNDBCToXYZ( - coerce_optional_dispatch(ndbc, "ent_list"), - coerce_optional_dispatch(coord, "vector"), - coerce_optional_dispatch(normal, "vector"), + check_and_coerce_optional(ndbc, EntList), + check_and_coerce_optional(coord, Vector), + check_and_coerce_optional(normal, Vector), ) def find_property(self, prop_type: int, prop_id: int) -> Property: @@ -653,11 +581,10 @@ def set_prohibited_gate_nodes(self, nodes: EntList | None, analysis: AnalysisTyp int : Number of constraints created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_prohibited_gate_nodes") - if nodes is not None: - check_type(nodes, EntList) + analysis = get_enum_value(analysis, AnalysisType) return self.boundary_conditions.SetProhibitedGateNodes( - coerce_optional_dispatch(nodes, "ent_list"), analysis + check_and_coerce_optional(nodes, EntList), analysis ) # pylint: disable-next=R0913,R0917 @@ -686,34 +613,25 @@ def create_one_sided_constraints( process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="create_one_sided_constraints" ) - if nodes is not None: - check_type(nodes, EntList) - if positive_trans is not None: - check_type(positive_trans, Vector) - if negative_trans is not None: - check_type(negative_trans, Vector) - if positive_trans_types is not None: - check_type(positive_trans_types, Vector) - if negative_trans_types is not None: - check_type(negative_trans_types, Vector) + if retract_time != 0: check_type(retract_time, (float, int)) positive_trans_types = self._check_vector(positive_trans_types) negative_trans_types = self._check_vector(negative_trans_types) return self.boundary_conditions.CreateOneSidedConstraints2( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(positive_trans, "vector"), - coerce_optional_dispatch(negative_trans, "vector"), - coerce_optional_dispatch(positive_trans_types, "vector"), - coerce_optional_dispatch(negative_trans_types, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(positive_trans, Vector), + check_and_coerce_optional(negative_trans, Vector), + check_and_coerce_optional(positive_trans_types, Vector), + check_and_coerce_optional(negative_trans_types, Vector), retract_time, ) positive_trans_types = self._check_vector(positive_trans_types) negative_trans_types = self._check_vector(negative_trans_types) return self.boundary_conditions.CreateOneSidedConstraints( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(positive_trans, "vector"), - coerce_optional_dispatch(negative_trans, "vector"), - coerce_optional_dispatch(positive_trans_types, "vector"), - coerce_optional_dispatch(negative_trans_types, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(positive_trans, Vector), + check_and_coerce_optional(negative_trans, Vector), + check_and_coerce_optional(positive_trans_types, Vector), + check_and_coerce_optional(negative_trans_types, Vector), ) diff --git a/src/moldflow/cad_manager.py b/src/moldflow/cad_manager.py index f2cfe9f..d0c05a2 100644 --- a/src/moldflow/cad_manager.py +++ b/src/moldflow/cad_manager.py @@ -9,7 +9,7 @@ from .ent_list import EntList from .vector import Vector from .logger import process_log, LogMessage -from .helper import check_type, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional from .com_proxy import safe_com @@ -60,14 +60,11 @@ def modify_cad_surfaces_by_normal( process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="modify_cad_surfaces_by_normal" ) - if faces is not None: - check_type(faces, EntList) - if transit_faces is not None: - check_type(transit_faces, EntList) + check_type(distance, (float, int)) return self.cad_manager.ModifyCADSurfacesByNormal( - coerce_optional_dispatch(faces, "ent_list"), - coerce_optional_dispatch(transit_faces, "ent_list"), + check_and_coerce_optional(faces, EntList), + check_and_coerce_optional(transit_faces, EntList), distance, ) @@ -89,14 +86,9 @@ def modify_cad_surfaces_by_vector( process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="modify_cad_surfaces_by_vector" ) - if faces is not None: - check_type(faces, EntList) - if transit_faces is not None: - check_type(transit_faces, EntList) - if vector is not None: - check_type(vector, Vector) + return self.cad_manager.ModifyCADSurfacesByVector( - coerce_optional_dispatch(faces, "ent_list"), - coerce_optional_dispatch(transit_faces, "ent_list"), - coerce_optional_dispatch(vector, "vector"), + check_and_coerce_optional(faces, EntList), + check_and_coerce_optional(transit_faces, EntList), + check_and_coerce_optional(vector, Vector), ) diff --git a/src/moldflow/com_proxy.py b/src/moldflow/com_proxy.py index 9c10aea..7d48e3e 100644 --- a/src/moldflow/com_proxy.py +++ b/src/moldflow/com_proxy.py @@ -13,7 +13,6 @@ from .common import LogMessage from .errors import raise_attribute_error - # ------------------------------------------------------------------ # Helper: Verify COM attribute existence # ------------------------------------------------------------------ diff --git a/src/moldflow/data_transform.py b/src/moldflow/data_transform.py index 81c8894..04b7c59 100644 --- a/src/moldflow/data_transform.py +++ b/src/moldflow/data_transform.py @@ -7,7 +7,7 @@ """ from .logger import process_log, LogMessage -from .helper import check_type, get_enum_value, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, get_enum_value from .com_proxy import safe_com from .common import TransformFunctions, TransformOperations, TransformScalarOperations from .integer_array import IntegerArray @@ -53,20 +53,13 @@ def func( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="func") func_name = get_enum_value(func_name, TransformFunctions) - if label_in is not None: - check_type(label_in, IntegerArray) - if data_in is not None: - check_type(data_in, DoubleArray) - if label_out is not None: - check_type(label_out, IntegerArray) - if data_out is not None: - check_type(data_out, DoubleArray) + return self.data_transform.Func( func_name, - coerce_optional_dispatch(label_in, "integer_array"), - coerce_optional_dispatch(data_in, "double_array"), - coerce_optional_dispatch(label_out, "integer_array"), - coerce_optional_dispatch(data_out, "double_array"), + check_and_coerce_optional(label_in, IntegerArray), + check_and_coerce_optional(data_in, DoubleArray), + check_and_coerce_optional(label_out, IntegerArray), + check_and_coerce_optional(data_out, DoubleArray), ) # pylint: disable=R0913, R0917 @@ -96,27 +89,17 @@ def op( bool: True if the operation was applied successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="op") - if label_1 is not None: - check_type(label_1, IntegerArray) - if data_1 is not None: - check_type(data_1, DoubleArray) + op = get_enum_value(op, TransformOperations) - if label_2 is not None: - check_type(label_2, IntegerArray) - if data_2 is not None: - check_type(data_2, DoubleArray) - if label_out is not None: - check_type(label_out, IntegerArray) - if data_out is not None: - check_type(data_out, DoubleArray) + return self.data_transform.Op( - coerce_optional_dispatch(label_1, "integer_array"), - coerce_optional_dispatch(data_1, "double_array"), + check_and_coerce_optional(label_1, IntegerArray), + check_and_coerce_optional(data_1, DoubleArray), op, - coerce_optional_dispatch(label_2, "integer_array"), - coerce_optional_dispatch(data_2, "double_array"), - coerce_optional_dispatch(label_out, "integer_array"), - coerce_optional_dispatch(data_out, "double_array"), + check_and_coerce_optional(label_2, IntegerArray), + check_and_coerce_optional(data_2, DoubleArray), + check_and_coerce_optional(label_out, IntegerArray), + check_and_coerce_optional(data_out, DoubleArray), ) # pylint: disable=R0913, R0917 @@ -144,21 +127,15 @@ def scalar( bool: True if the scalar operation was applied successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="scalar") - if label_in is not None: - check_type(label_in, IntegerArray) - if data_in is not None: - check_type(data_in, DoubleArray) + op = get_enum_value(op, TransformScalarOperations) check_type(scalar_value, (float, int)) - if label_out is not None: - check_type(label_out, IntegerArray) - if data_out is not None: - check_type(data_out, DoubleArray) + return self.data_transform.Scalar( - coerce_optional_dispatch(label_in, "integer_array"), - coerce_optional_dispatch(data_in, "double_array"), + check_and_coerce_optional(label_in, IntegerArray), + check_and_coerce_optional(data_in, DoubleArray), op, scalar_value, - coerce_optional_dispatch(label_out, "integer_array"), - coerce_optional_dispatch(data_out, "double_array"), + check_and_coerce_optional(label_out, IntegerArray), + check_and_coerce_optional(data_out, DoubleArray), ) diff --git a/src/moldflow/diagnosis_manager.py b/src/moldflow/diagnosis_manager.py index 17dc75d..0618415 100644 --- a/src/moldflow/diagnosis_manager.py +++ b/src/moldflow/diagnosis_manager.py @@ -9,7 +9,7 @@ from .logger import process_log from .common import LogMessage -from .helper import check_type, check_min_max, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, check_min_max from .com_proxy import safe_com from .ent_list import EntList from .mesh_summary import MeshSummary @@ -129,14 +129,13 @@ def show_connect( visible (bool): Show/hide the selected mesh diagnosis. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_connect") - if nodes is not None: - check_type(nodes, EntList) + check_type(ex_beam, bool) check_type(assign_layer, bool) check_type(show_txt, bool) check_type(visible, bool) self.diagnosis_manager.ShowConnect2( - coerce_optional_dispatch(nodes, "ent_list"), ex_beam, assign_layer, show_txt, visible + check_and_coerce_optional(nodes, EntList), ex_beam, assign_layer, show_txt, visible ) def show_edges( @@ -339,16 +338,13 @@ def get_thickness_diagnosis( check_type(max_value, (float, int)) check_min_max(min_value, max_value) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetThicknessDiagnosis2( min_value, max_value, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_aspect_ratio_diagnosis( @@ -380,17 +376,14 @@ def get_aspect_ratio_diagnosis( check_min_max(min_value, max_value) check_type(std_ar, bool) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetAspectRatioDiagnosis2( min_value, max_value, std_ar, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_connectivity_diagnosis( @@ -415,20 +408,16 @@ def get_connectivity_diagnosis( int: The number of connectivity diagnostics. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_connectivity_diagnosis") - if nodes is not None: - check_type(nodes, EntList) + check_type(ex_beam, bool) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetConnectivityDiagnosis2( - coerce_optional_dispatch(nodes, "ent_list"), + check_and_coerce_optional(nodes, EntList), ex_beam, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_edges_diagnosis( @@ -453,15 +442,12 @@ def get_edges_diagnosis( process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_edges_diagnosis") check_type(non_manifold, bool) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetEdgesDiagnosis2( non_manifold, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_overlap_diagnosis( @@ -489,16 +475,13 @@ def get_overlap_diagnosis( check_type(overlap, bool) check_type(intersect, bool) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetOverlapDiagnosis2( overlap, intersect, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_occurrence_diagnosis( @@ -517,14 +500,11 @@ def get_occurrence_diagnosis( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_occurrence_diagnosis") check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetOccurrenceDiagnosis2( visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_match_info_diagnosis( @@ -541,13 +521,10 @@ def get_match_info_diagnosis( int: The number of mesh match diagnostics. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_match_info_diagnosis") - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetMatchInfoDiagnosis( - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_orientation_diagnosis( @@ -566,14 +543,11 @@ def get_orientation_diagnosis( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_orientation_diagnosis") check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetOrientationDiagnosis2( visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def show_zero_area_elements( @@ -619,15 +593,12 @@ def get_zero_area_elements_diagnosis( ) check_type(min_value, (float, int)) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetZeroAreaElementsDiagnosis2( min_value, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_mesh_summary( @@ -760,17 +731,14 @@ def get_surface_with_bad_trim_curve( check_type(inner_loop, bool) check_type(surf_def, bool) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetSurfWithBadTrimCurv( outer_loop, inner_loop, surf_def, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_surface_with_free_trim_curve( @@ -800,16 +768,13 @@ def get_surface_with_free_trim_curve( check_type(free, bool) check_type(non_manifold, bool) check_type(visible, bool) - if element_id is not None: - check_type(element_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + return self.diagnosis_manager.GetSurfWithFreeTrimCurv( free, non_manifold, visible, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) # pylint: disable=R0913, R0917 @@ -1001,11 +966,10 @@ def get_inverted_tetras(self, visible: bool, tetra_id: IntegerArray | None) -> i int: The number of inverted tetras. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_inverted_tetras") - if tetra_id is not None: - check_type(tetra_id, IntegerArray) + check_type(visible, bool) return self.diagnosis_manager.GetInvertedTetras( - visible, coerce_optional_dispatch(tetra_id, "integer_array") + visible, check_and_coerce_optional(tetra_id, IntegerArray) ) def get_collapsed_faces(self, visible: bool, tetra_id: IntegerArray | None) -> int: @@ -1020,11 +984,10 @@ def get_collapsed_faces(self, visible: bool, tetra_id: IntegerArray | None) -> i int: The number of collapsed faces. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_collapsed_faces") - if tetra_id is not None: - check_type(tetra_id, IntegerArray) + check_type(visible, bool) return self.diagnosis_manager.GetCollapsedFaces( - visible, coerce_optional_dispatch(tetra_id, "integer_array") + visible, check_and_coerce_optional(tetra_id, IntegerArray) ) def get_insufficient_refinement_through_thickness( @@ -1048,11 +1011,10 @@ def get_insufficient_refinement_through_thickness( name="get_insufficient_refinement_through_thickness", ) check_type(min_layer, int) - if tetra_id is not None: - check_type(tetra_id, IntegerArray) + check_type(visible, bool) return self.diagnosis_manager.GetInsufficientRefinementThroughThickness( - min_layer, visible, coerce_optional_dispatch(tetra_id, "integer_array") + min_layer, visible, check_and_coerce_optional(tetra_id, IntegerArray) ) def get_internal_long_edges( @@ -1076,16 +1038,13 @@ def get_internal_long_edges( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_internal_long_edges") check_type(max_edge_length_ratio, (float, int)) - if tetra_id is not None: - check_type(tetra_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + check_type(visible, bool) return self.diagnosis_manager.GetInternalLongEdges( max_edge_length_ratio, visible, - coerce_optional_dispatch(tetra_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(tetra_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_tetras_with_extremely_large_volume( @@ -1114,16 +1073,13 @@ def get_tetras_with_extremely_large_volume( name="get_tetras_with_extremely_large_volume", ) check_type(max_volume_ratio, (float, int)) - if tetra_id is not None: - check_type(tetra_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + check_type(visible, bool) return self.diagnosis_manager.GetTetrasWithExtremelyLargeVolume( max_volume_ratio, visible, - coerce_optional_dispatch(tetra_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(tetra_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_tetras_with_high_aspect_ratio( @@ -1149,16 +1105,13 @@ def get_tetras_with_high_aspect_ratio( __name__, LogMessage.FUNCTION_CALL, locals(), name="get_tetras_with_high_aspect_ratio" ) check_type(max_aspect_ratio, (float, int)) - if tetra_id is not None: - check_type(tetra_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + check_type(visible, bool) return self.diagnosis_manager.GetTetrasWithHighAspectRatio( max_aspect_ratio, visible, - coerce_optional_dispatch(tetra_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(tetra_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_tetras_with_extreme_min_angle_between_faces( @@ -1187,16 +1140,13 @@ def get_tetras_with_extreme_min_angle_between_faces( name="get_tetras_with_extreme_min_angle_between_faces", ) check_type(min_angle, (float, int)) - if tetra_id is not None: - check_type(tetra_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + check_type(visible, bool) return self.diagnosis_manager.GetTetrasWithExtremeMinAngleBetweenFaces( min_angle, visible, - coerce_optional_dispatch(tetra_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(tetra_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) def get_tetras_with_extreme_max_angle_between_faces( @@ -1225,14 +1175,11 @@ def get_tetras_with_extreme_max_angle_between_faces( name="get_tetras_with_extreme_max_angle_between_faces", ) check_type(max_angle, (float, int)) - if tetra_id is not None: - check_type(tetra_id, IntegerArray) - if value is not None: - check_type(value, DoubleArray) + check_type(visible, bool) return self.diagnosis_manager.GetTetrasWithExtremeMaxAngleBetweenFaces( max_angle, visible, - coerce_optional_dispatch(tetra_id, "integer_array"), - coerce_optional_dispatch(value, "double_array"), + check_and_coerce_optional(tetra_id, IntegerArray), + check_and_coerce_optional(value, DoubleArray), ) diff --git a/src/moldflow/ent_list.py b/src/moldflow/ent_list.py index 1c39a4c..600e6f8 100644 --- a/src/moldflow/ent_list.py +++ b/src/moldflow/ent_list.py @@ -6,7 +6,7 @@ EntList Class API Wrapper """ -from .helper import check_index, check_type, coerce_optional_dispatch +from .helper import check_index, check_type, check_and_coerce_optional from .com_proxy import safe_com, expose_oleobj from .predicate import Predicate from .common import LogMessage @@ -65,9 +65,8 @@ def select_from_predicate(self, predicate: Predicate | None) -> None: inclusion of an entity. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="select_from_predicate") - if predicate is not None: - check_type(predicate, Predicate) - self.ent_list.SelectFromPredicate(coerce_optional_dispatch(predicate, "predicate")) + + self.ent_list.SelectFromPredicate(check_and_coerce_optional(predicate, Predicate)) def convert_to_string(self) -> str: """ diff --git a/src/moldflow/errors.py b/src/moldflow/errors.py index a1209da..cefc4c0 100644 --- a/src/moldflow/errors.py +++ b/src/moldflow/errors.py @@ -70,7 +70,6 @@ def raise_save_error(saving: str, file_name: str) -> NoReturn: """ Raise a SaveError if the save operation fails. - Args: saving (str): The operation that failed. file_name (str): The name of the file that could not be saved. diff --git a/src/moldflow/folder_manager.py b/src/moldflow/folder_manager.py index f423f53..0777386 100644 --- a/src/moldflow/folder_manager.py +++ b/src/moldflow/folder_manager.py @@ -9,7 +9,7 @@ from .logger import process_log, LogMessage from .ent_list import EntList from .common import EntityType, DisplayOption -from .helper import get_enum_value, check_type, check_range, coerce_optional_dispatch +from .helper import get_enum_value, check_type, check_and_coerce_optional, check_range from .com_proxy import safe_com @@ -49,9 +49,8 @@ def create_child_layer(self, folder: EntList | None) -> EntList: EntList: The created child layer. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_child_layer") - if folder is not None: - check_type(folder, EntList) - result = self.folder_manager.CreateChildLayer(coerce_optional_dispatch(folder, "ent_list")) + + result = self.folder_manager.CreateChildLayer(check_and_coerce_optional(folder, EntList)) if result is None: return None return EntList(result) @@ -67,9 +66,8 @@ def create_child_folder(self, folder: EntList | None) -> EntList: EntList: The created child folder. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_child_folder") - if folder is not None: - check_type(folder, EntList) - result = self.folder_manager.CreateChildFolder(coerce_optional_dispatch(folder, "ent_list")) + + result = self.folder_manager.CreateChildFolder(check_and_coerce_optional(folder, EntList)) if result is None: return None return EntList(result) @@ -86,13 +84,9 @@ def add_objects_to_folder(self, objects: EntList | None, folder: EntList | None) bool: True if the objects were added successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_objects_to_folder") - if objects is not None: - check_type(objects, EntList) - if folder is not None: - check_type(folder, EntList) + return self.folder_manager.AddObjectsToFolder( - coerce_optional_dispatch(objects, "ent_list"), - coerce_optional_dispatch(folder, "ent_list"), + check_and_coerce_optional(objects, EntList), check_and_coerce_optional(folder, EntList) ) def remove_objects_from_folder(self, objects: EntList | None) -> bool: @@ -106,10 +100,9 @@ def remove_objects_from_folder(self, objects: EntList | None) -> bool: bool: True if the objects were removed successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="remove_objects_from_folder") - if objects is not None: - check_type(objects, EntList) + return self.folder_manager.RemoveObjectsFromFolder( - coerce_optional_dispatch(objects, "ent_list") + check_and_coerce_optional(objects, EntList) ) def create_entity_list(self) -> EntList: @@ -138,11 +131,10 @@ def delete_folder(self, folder: EntList | None, move_layers: bool) -> bool: bool: True if the folder was deleted successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="delete_folder") - if folder is not None: - check_type(folder, EntList) + check_type(move_layers, bool) return self.folder_manager.DeleteFolder( - coerce_optional_dispatch(folder, "ent_list"), move_layers + check_and_coerce_optional(folder, EntList), move_layers ) def toggle_folder(self, folder: EntList | None) -> bool: @@ -156,9 +148,8 @@ def toggle_folder(self, folder: EntList | None) -> bool: bool: True if the folder was toggled successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="toggle_folder") - if folder is not None: - check_type(folder, EntList) - return self.folder_manager.ToggleFolder(coerce_optional_dispatch(folder, "ent_list")) + + return self.folder_manager.ToggleFolder(check_and_coerce_optional(folder, EntList)) # pylint: disable-next=R0913, R0917 def expand_folder( @@ -187,8 +178,7 @@ def expand_folder( int: The number of entities affected. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="expand_folder") - if folder is not None: - check_type(folder, EntList) + # pylint: disable=R0801 check_type(levels, int) check_type(expand_new_layer, bool) @@ -197,7 +187,7 @@ def expand_folder( check_type(inc_tetras, bool) check_type(inc_beams, bool) return self.folder_manager.ExpandFolder( - coerce_optional_dispatch(folder, "ent_list"), + check_and_coerce_optional(folder, EntList), levels, expand_new_layer, inc_nodes, @@ -218,10 +208,9 @@ def set_folder_name(self, folder: EntList | None, name: str) -> bool: bool: True if the folder name was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_folder_name") - if folder is not None: - check_type(folder, EntList) + check_type(name, str) - return self.folder_manager.SetFolderName(coerce_optional_dispatch(folder, "ent_list"), name) + return self.folder_manager.SetFolderName(check_and_coerce_optional(folder, EntList), name) def show_all_folders(self) -> bool: """ @@ -245,10 +234,9 @@ def show_folders(self, folders: EntList | None, show: bool) -> bool: bool: True if the folders were shown/hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_folders") - if folders is not None: - check_type(folders, EntList) + check_type(show, bool) - return self.folder_manager.ShowFolders(coerce_optional_dispatch(folders, "ent_list"), show) + return self.folder_manager.ShowFolders(check_and_coerce_optional(folders, EntList), show) # pylint: disable-next=R0913, R0917 def set_type_color( @@ -275,8 +263,7 @@ def set_type_color( int: The integer identifier for the color """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_color") - if folder is not None: - check_type(folder, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(default, bool) check_type(red, int) @@ -286,7 +273,7 @@ def set_type_color( check_range(green, 0, 255, True, True) check_range(blue, 0, 255, True, True) return self.folder_manager.SetTypeColor( - coerce_optional_dispatch(folder, "ent_list"), entity_type, default, red, green, blue + check_and_coerce_optional(folder, EntList), entity_type, default, red, green, blue ) def set_type_visible( @@ -304,12 +291,11 @@ def set_type_visible( bool: True if the visibility was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_visible") - if folder is not None: - check_type(folder, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(visible, bool) return self.folder_manager.SetTypeVisible( - coerce_optional_dispatch(folder, "ent_list"), entity_type, visible + check_and_coerce_optional(folder, EntList), entity_type, visible ) def set_type_display_option( @@ -353,12 +339,11 @@ def set_type_display_option( bool: True if the display option was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_display_option") - if folder is not None: - check_type(folder, EntList) + entity_type = get_enum_value(entity_type, EntityType) option = get_enum_value(option, DisplayOption) return self.folder_manager.SetTypeDisplayOption( - coerce_optional_dispatch(folder, "ent_list"), entity_type, option + check_and_coerce_optional(folder, EntList), entity_type, option ) def get_first(self) -> EntList: @@ -385,9 +370,8 @@ def get_next(self, folder: EntList | None) -> EntList: EntList: The next folder. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next") - if folder is not None: - check_type(folder, EntList) - result = self.folder_manager.GetNext(coerce_optional_dispatch(folder, "ent_list")) + + result = self.folder_manager.GetNext(check_and_coerce_optional(folder, EntList)) if result is None: return None return EntList(result) @@ -403,9 +387,8 @@ def get_name(self, folder: EntList | None) -> str: str: The name of the folder. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_name") - if folder is not None: - check_type(folder, EntList) - return self.folder_manager.GetName(coerce_optional_dispatch(folder, "ent_list")) + + return self.folder_manager.GetName(check_and_coerce_optional(folder, EntList)) def show_labels(self, folder: EntList | None, show: bool) -> bool: """ @@ -419,10 +402,9 @@ def show_labels(self, folder: EntList | None, show: bool) -> bool: bool: True if the labels were shown/hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_labels") - if folder is not None: - check_type(folder, EntList) + check_type(show, bool) - return self.folder_manager.ShowLabels(coerce_optional_dispatch(folder, "ent_list"), show) + return self.folder_manager.ShowLabels(check_and_coerce_optional(folder, EntList), show) def show_glyphs(self, folder: EntList | None, show: bool) -> bool: """ @@ -436,10 +418,9 @@ def show_glyphs(self, folder: EntList | None, show: bool) -> bool: bool: True if the glyphs were shown/hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_glyphs") - if folder is not None: - check_type(folder, EntList) + check_type(show, bool) - return self.folder_manager.ShowGlyphs(coerce_optional_dispatch(folder, "ent_list"), show) + return self.folder_manager.ShowGlyphs(check_and_coerce_optional(folder, EntList), show) def set_type_show_labels( self, folder: EntList | None, entity_type: EntityType | str, show: bool @@ -456,12 +437,11 @@ def set_type_show_labels( bool: True if the label visibility was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_show_labels") - if folder is not None: - check_type(folder, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(show, bool) return self.folder_manager.SetTypeShowLabels( - coerce_optional_dispatch(folder, "ent_list"), entity_type, show + check_and_coerce_optional(folder, EntList), entity_type, show ) def set_type_show_glyphs( @@ -479,12 +459,11 @@ def set_type_show_glyphs( bool: True if the glyph visibility was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_show_glyphs") - if folder is not None: - check_type(folder, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(show, bool) return self.folder_manager.SetTypeShowGlyphs( - coerce_optional_dispatch(folder, "ent_list"), entity_type, show + check_and_coerce_optional(folder, EntList), entity_type, show ) def create_folder_by_name(self, name: str) -> EntList: @@ -532,9 +511,8 @@ def hide_all_other_folders(self, folder: EntList | None) -> bool: bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="hide_all_other_folders") - if folder is not None: - check_type(folder, EntList) - return self.folder_manager.HideAllOtherFolders(coerce_optional_dispatch(folder, "ent_list")) + + return self.folder_manager.HideAllOtherFolders(check_and_coerce_optional(folder, EntList)) def remove_empty_folders(self) -> bool: """ @@ -558,9 +536,8 @@ def allow_clipping(self, folder: EntList | None, checked: bool) -> bool: bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="allow_clipping") - if folder is not None: - check_type(folder, EntList) + check_type(checked, bool) return self.folder_manager.AllowClipping( - coerce_optional_dispatch(folder, "ent_list"), checked + check_and_coerce_optional(folder, EntList), checked ) diff --git a/src/moldflow/helper.py b/src/moldflow/helper.py index c2d1a90..4a5ae14 100644 --- a/src/moldflow/helper.py +++ b/src/moldflow/helper.py @@ -45,13 +45,13 @@ def get_enum_value(value, enum: Enum): return value -def check_type(value, types: tuple): +def check_type(value, types: tuple | type): """ Check if the value is of the specified type(s). Args: value: The value to check. - types (tuple): A tuple of types to check against. + types (tuple | type): A tuple of types to check against, or a single type. Returns: bool: True if the value is of the specified type(s), otherwise raises a TypeError. @@ -76,6 +76,34 @@ def check_type(value, types: tuple): process_log(__name__, LogMessage.VALID_INPUT) +def check_optional_type(value, types: tuple | type): + """ + Check if the value is of the specified type(s) or None. + + This function is used to validate optional parameters that may be None or a specific type. + It provides standardized handling of None arguments across API calls. + + Args: + value: The value to check. Can be None or of the specified type(s). + types (tuple | type): A tuple of types to check against, or a single type (excluding None). + + Returns: + bool: True if the value is None or of the specified type(s), otherwise raises a TypeError. + + Raises: + TypeError: If the value is not None and not of the specified type(s). + + Notes: + - None is always considered valid. + - The function handles the special case where in python `bool` is a subclass of `int`. + - If `types` is not a tuple, it is treated as a single type. + """ + if value is None: + process_log(__name__, LogMessage.VALID_INPUT) + return + check_type(value, types) + + def _compare(value1, value2, inclusive): """ Compare two values @@ -337,3 +365,69 @@ def coerce_optional_dispatch(value, attr_name: str | None = None): if attr_name: value = getattr(value, attr_name) return value + + +# Type to attribute name mapping for COM objects +_TYPE_TO_ATTR_MAP = { + 'EntList': 'ent_list', + 'Vector': 'vector', + 'Property': 'prop', + 'Predicate': 'predicate', + 'IntegerArray': 'integer_array', + 'DoubleArray': 'double_array', + 'BoundaryList': 'boundary_list', + 'VectorArray': 'vector_array', + 'StringArray': 'string_array', +} + + +def check_and_coerce_optional(value, expected_type: type): + """ + Check if the value is of the expected type or None, and coerce it for COM dispatch. + + This function combines type validation and COM coercion into a single operation, + providing standardized handling of optional COM object parameters. + + - If value is None, returns a null IDispatch VARIANT + - If value is not None, validates the type and unwraps the COM object attribute + - For primitive types (int, float, str, bool), returns the value as-is after validation + + Args: + value: The value to check and coerce. Can be None or of the expected type. + expected_type (type): The expected type to check against. + + Returns: + VARIANT or value: The coerced COM object (VARIANT) or the validated primitive value. + + Raises: + TypeError: If the value is not None and not of the expected type. + + Examples: + >>> nodes = EntList(...) + >>> coerced = check_and_coerce_optional(nodes, EntList) + >>> # Returns nodes.ent_list + + >>> check_and_coerce_optional(None, EntList) + >>> # Returns variant_null_idispatch() + + >>> check_and_coerce_optional(42, int) + >>> # Returns 42 (primitive types are passed through) + """ + # First validate the type + check_optional_type(value, expected_type) + + # If None, return null dispatch + if value is None: + return variant_null_idispatch() + + # Get the type name + type_name = expected_type.__name__ + + # Check if this is a COM object type that needs unwrapping + attr_name = _TYPE_TO_ATTR_MAP.get(type_name) + + if attr_name: + # COM object - unwrap the attribute + return getattr(value, attr_name) + # Primitive type or unknown type - return as-is + return value diff --git a/src/moldflow/i18n.py b/src/moldflow/i18n.py index 1768360..c26b53b 100644 --- a/src/moldflow/i18n.py +++ b/src/moldflow/i18n.py @@ -11,7 +11,6 @@ import gettext from typing import Callable - _translator: Callable[[str], str] | None = None diff --git a/src/moldflow/layer_manager.py b/src/moldflow/layer_manager.py index 8ade557..1595396 100644 --- a/src/moldflow/layer_manager.py +++ b/src/moldflow/layer_manager.py @@ -9,7 +9,7 @@ from .ent_list import EntList from .common import EntityType, DisplayOption from .logger import process_log, LogMessage -from .helper import check_type, check_range, get_enum_value, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, check_range, get_enum_value from .com_proxy import safe_com @@ -39,9 +39,8 @@ def active(self, layer: EntList | None) -> bool: bool: True if the layer is active, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="active") - if layer is not None: - check_type(layer, EntList) - return self.layer_manager.Active(coerce_optional_dispatch(layer, "ent_list")) + + return self.layer_manager.Active(check_and_coerce_optional(layer, EntList)) def create_layer(self) -> bool: """ @@ -64,9 +63,8 @@ def activate_layer(self, layer: EntList | None) -> bool: bool: True if the layer was activated successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="activate_layer") - if layer is not None: - check_type(layer, EntList) - return self.layer_manager.ActivateLayer(coerce_optional_dispatch(layer, "ent_list")) + + return self.layer_manager.ActivateLayer(check_and_coerce_optional(layer, EntList)) def create_entity_list(self) -> EntList: """ @@ -93,12 +91,9 @@ def assign_to_layer(self, elems: EntList | None, layer: EntList | None) -> int: int: The number of elements assigned to the layer. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="assign_to_layer") - if elems is not None: - check_type(elems, EntList) - if layer is not None: - check_type(layer, EntList) + return self.layer_manager.AssignToLayer( - coerce_optional_dispatch(elems, "ent_list"), coerce_optional_dispatch(layer, "ent_list") + check_and_coerce_optional(elems, EntList), check_and_coerce_optional(layer, EntList) ) def delete_layer(self, layer: EntList | None, move_ent: bool) -> bool: @@ -114,10 +109,9 @@ def delete_layer(self, layer: EntList | None, move_ent: bool) -> bool: bool: True if the layer was deleted successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="delete_layer") - if layer is not None: - check_type(layer, EntList) + check_type(move_ent, bool) - return self.layer_manager.DeleteLayer(coerce_optional_dispatch(layer, "ent_list"), move_ent) + return self.layer_manager.DeleteLayer(check_and_coerce_optional(layer, EntList), move_ent) def toggle_layer(self, layer: EntList | None) -> bool: """ @@ -130,9 +124,8 @@ def toggle_layer(self, layer: EntList | None) -> bool: bool: True if the layer was toggled successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="toggle_layer") - if layer is not None: - check_type(layer, EntList) - return self.layer_manager.ToggleLayer(coerce_optional_dispatch(layer, "ent_list")) + + return self.layer_manager.ToggleLayer(check_and_coerce_optional(layer, EntList)) # pylint: disable-next=R0913, R0917 def expand_layer( @@ -161,8 +154,7 @@ def expand_layer( int: The number of elements expanded. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="expand_layer") - if layer is not None: - check_type(layer, EntList) + check_type(levels, int) check_type(expand_new_layer, bool) check_type(inc_nodes, bool) @@ -170,7 +162,7 @@ def expand_layer( check_type(inc_tetras, bool) check_type(inc_beams, bool) return self.layer_manager.ExpandLayer2( - coerce_optional_dispatch(layer, "ent_list"), + check_and_coerce_optional(layer, EntList), levels, expand_new_layer, inc_nodes, @@ -191,10 +183,9 @@ def set_layer_name(self, layer: EntList | None, name: str) -> bool: bool: True if the name was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_layer_name") - if layer is not None: - check_type(layer, EntList) + check_type(name, str) - return self.layer_manager.SetLayerName(coerce_optional_dispatch(layer, "ent_list"), name) + return self.layer_manager.SetLayerName(check_and_coerce_optional(layer, EntList), name) def show_all_layers(self) -> bool: """ @@ -218,10 +209,9 @@ def show_layers(self, layers: EntList | None, show: bool) -> bool: bool: True if the layers were shown or hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_layers") - if layers is not None: - check_type(layers, EntList) + check_type(show, bool) - return self.layer_manager.ShowLayers(coerce_optional_dispatch(layers, "ent_list"), show) + return self.layer_manager.ShowLayers(check_and_coerce_optional(layers, EntList), show) # pylint: disable-next=R0913, R0917 def set_type_color( @@ -248,15 +238,14 @@ def set_type_color( int: The integer identifier for the color """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_color") - if layer is not None: - check_type(layer, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(default, bool) check_range(red, 0, 255, True, True) check_range(blue, 0, 255, True, True) check_range(green, 0, 255, True, True) return self.layer_manager.SetTypeColor( - coerce_optional_dispatch(layer, "ent_list"), entity_type, default, red, blue, green + check_and_coerce_optional(layer, EntList), entity_type, default, red, blue, green ) def set_type_visible( @@ -274,12 +263,11 @@ def set_type_visible( bool: True if the visibility was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_visible") - if layer is not None: - check_type(layer, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(visible, bool) return self.layer_manager.SetTypeVisible( - coerce_optional_dispatch(layer, "ent_list"), entity_type, visible + check_and_coerce_optional(layer, EntList), entity_type, visible ) def set_type_display_option( @@ -323,12 +311,11 @@ def set_type_display_option( bool: True if the display option was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_display_option") - if layer is not None: - check_type(layer, EntList) + entity_type = get_enum_value(entity_type, EntityType) option = get_enum_value(option, DisplayOption) return self.layer_manager.SetTypeDisplayOption( - coerce_optional_dispatch(layer, "ent_list"), entity_type, option + check_and_coerce_optional(layer, EntList), entity_type, option ) def get_first(self) -> EntList: @@ -355,9 +342,8 @@ def get_next(self, layer: EntList | None) -> EntList: EntList: The next layer. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next") - if layer is not None: - check_type(layer, EntList) - result = self.layer_manager.GetNext(coerce_optional_dispatch(layer, "ent_list")) + + result = self.layer_manager.GetNext(check_and_coerce_optional(layer, EntList)) if result is None: return None return EntList(result) @@ -373,9 +359,8 @@ def get_name(self, layer: EntList | None) -> str: str: The name of the layer. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_name") - if layer is not None: - check_type(layer, EntList) - return self.layer_manager.GetName(coerce_optional_dispatch(layer, "ent_list")) + + return self.layer_manager.GetName(check_and_coerce_optional(layer, EntList)) def show_labels(self, layer: EntList | None, show: bool) -> bool: """ @@ -389,10 +374,9 @@ def show_labels(self, layer: EntList | None, show: bool) -> bool: bool: True if the labels were shown or hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_labels") - if layer is not None: - check_type(layer, EntList) + check_type(show, bool) - return self.layer_manager.ShowLabels(coerce_optional_dispatch(layer, "ent_list"), show) + return self.layer_manager.ShowLabels(check_and_coerce_optional(layer, EntList), show) def show_glyphs(self, layer: EntList | None, show: bool) -> bool: """ @@ -406,10 +390,9 @@ def show_glyphs(self, layer: EntList | None, show: bool) -> bool: bool: True if the glyphs were shown or hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_glyphs") - if layer is not None: - check_type(layer, EntList) + check_type(show, bool) - return self.layer_manager.ShowGlyphs(coerce_optional_dispatch(layer, "ent_list"), show) + return self.layer_manager.ShowGlyphs(check_and_coerce_optional(layer, EntList), show) def set_type_show_labels( self, layer: EntList | None, entity_type: EntityType | str, show: bool @@ -426,12 +409,11 @@ def set_type_show_labels( bool: True if the label visibility was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_show_labels") - if layer is not None: - check_type(layer, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(show, bool) return self.layer_manager.SetTypeShowLabels( - coerce_optional_dispatch(layer, "ent_list"), entity_type, show + check_and_coerce_optional(layer, EntList), entity_type, show ) def set_type_show_glyphs( @@ -449,12 +431,11 @@ def set_type_show_glyphs( bool: True if the glyphs visibility was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_type_show_glyphs") - if layer is not None: - check_type(layer, EntList) + entity_type = get_enum_value(entity_type, EntityType) check_type(show, bool) return self.layer_manager.SetTypeShowGlyphs( - coerce_optional_dispatch(layer, "ent_list"), entity_type, show + check_and_coerce_optional(layer, EntList), entity_type, show ) def create_layer_by_name(self, name: str) -> EntList: @@ -502,9 +483,8 @@ def hide_all_other_layers(self, layer: EntList | None) -> bool: bool: True if all other layers were hidden successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="hide_all_other_layers") - if layer is not None: - check_type(layer, EntList) - return self.layer_manager.HideAllOtherLayers(coerce_optional_dispatch(layer, "ent_list")) + + return self.layer_manager.HideAllOtherLayers(check_and_coerce_optional(layer, EntList)) def remove_empty_layers(self) -> bool: """ @@ -527,9 +507,8 @@ def get_activated(self, layer: EntList | None) -> bool: bool: True if the layer is visible, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_activated") - if layer is not None: - check_type(layer, EntList) - return self.layer_manager.GetActivated(coerce_optional_dispatch(layer, "ent_list")) + + return self.layer_manager.GetActivated(check_and_coerce_optional(layer, EntList)) def get_type_visible(self, layer: EntList | None, entity_type: EntityType | str) -> bool: """ @@ -543,11 +522,10 @@ def get_type_visible(self, layer: EntList | None, entity_type: EntityType | str) bool: True if the entity type is visible, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_type_visible") - if layer is not None: - check_type(layer, EntList) + entity_type = get_enum_value(entity_type, EntityType) return self.layer_manager.GetTypeVisible( - coerce_optional_dispatch(layer, "ent_list"), entity_type + check_and_coerce_optional(layer, EntList), entity_type ) def get_number_of_layers(self) -> int: @@ -572,9 +550,6 @@ def allow_clipping(self, layer: EntList | None, checked: bool) -> bool: bool: True if the clipping was set successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="allow_clipping") - if layer is not None: - check_type(layer, EntList) + check_type(checked, bool) - return self.layer_manager.AllowClipping( - coerce_optional_dispatch(layer, "ent_list"), checked - ) + return self.layer_manager.AllowClipping(check_and_coerce_optional(layer, EntList), checked) diff --git a/src/moldflow/material_finder.py b/src/moldflow/material_finder.py index 8cf8999..5c1f06d 100644 --- a/src/moldflow/material_finder.py +++ b/src/moldflow/material_finder.py @@ -9,7 +9,7 @@ from .prop import Property from .common import MaterialDatabase, MaterialDatabaseType from .logger import process_log -from .helper import check_type, get_enum_value, coerce_optional_dispatch +from .helper import check_and_coerce_optional, get_enum_value from .com_proxy import safe_com from .common import LogMessage @@ -72,9 +72,8 @@ def get_next_material(self, material: Property | None) -> Property: Property: The next material. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_material") - if material is not None: - check_type(material, Property) - material_disp = coerce_optional_dispatch(material, "prop") + + material_disp = check_and_coerce_optional(material, Property) result = self.material_finder.GetNextMaterial(material_disp) if result is None: return None diff --git a/src/moldflow/mesh_editor.py b/src/moldflow/mesh_editor.py index 88e207f..2287d09 100644 --- a/src/moldflow/mesh_editor.py +++ b/src/moldflow/mesh_editor.py @@ -13,7 +13,7 @@ from .ent_list import EntList from .vector import Vector from .prop import Property -from .helper import check_type, check_range, check_is_non_negative, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, check_range, check_is_non_negative from .com_proxy import safe_com @@ -80,14 +80,11 @@ def swap_edge( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="swap_edges") - if tri1 is not None: - check_type(tri1, EntList) - if tri2 is not None: - check_type(tri2, EntList) + check_type(feat_allow, bool) return self.mesh_editor.SwapEdge( - coerce_optional_dispatch(tri1, "ent_list"), - coerce_optional_dispatch(tri2, "ent_list"), + check_and_coerce_optional(tri1, EntList), + check_and_coerce_optional(tri2, EntList), feat_allow, ) @@ -104,10 +101,9 @@ def stitch_free_edges(self, nodes: EntList | None, tolerance: float) -> bool: """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="stitch_free_edges") check_type(tolerance, float) - if nodes is not None: - check_type(nodes, EntList) + return self.mesh_editor.StitchFreeEdges2( - coerce_optional_dispatch(nodes, "ent_list"), tolerance + check_and_coerce_optional(nodes, EntList), tolerance ) def insert_node(self, node1: EntList | None, node2: EntList | None) -> EntList: @@ -121,12 +117,9 @@ def insert_node(self, node1: EntList | None, node2: EntList | None) -> EntList: The new node. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="insert_node") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) + result = self.mesh_editor.InsertNode( - coerce_optional_dispatch(node1, "ent_list"), coerce_optional_dispatch(node2, "ent_list") + check_and_coerce_optional(node1, EntList), check_and_coerce_optional(node2, EntList) ) if result is None: return None @@ -149,25 +142,18 @@ def insert_node_in_tri( The new node at the centroid of triangle. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="insert_node_in_tri") - if node1 is not None: - check_type(node1, EntList) if node2 is None and node3 is None: check_range(node1.size, 3, 3, True, True) - result = self.mesh_editor.InsertNodeInTri2(coerce_optional_dispatch(node1, "ent_list")) + result = self.mesh_editor.InsertNodeInTri2(check_and_coerce_optional(node1, EntList)) if result is None: return None return EntList(result) - if node2 is not None: - check_type(node2, EntList) - if node3 is not None: - check_type(node3, EntList) - result = self.mesh_editor.InsertNodeInTri( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(node3, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(node3, EntList), ) if result is None: @@ -196,25 +182,19 @@ def insert_node_in_tet( The new node at the centroid of tetrahedron. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="insert_node_in_tet") - if node1 is not None: - check_type(node1, EntList) + if node2 is None or node3 is None or node4 is None: check_range(node1.size, 4, 4, True, True) - result = self.mesh_editor.InsertNodeInTet(coerce_optional_dispatch(node1, "ent_list")) + result = self.mesh_editor.InsertNodeInTet(check_and_coerce_optional(node1, EntList)) if result is None: return None return EntList(result) - if node2 is not None: - check_type(node2, EntList) - if node3 is not None: - check_type(node3, EntList) - if node4 is not None: - check_type(node4, EntList) + result = self.mesh_editor.InsertNodeInTetByNodes( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(node3, "ent_list"), - coerce_optional_dispatch(node4, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(node3, EntList), + check_and_coerce_optional(node4, EntList), ) if result is None: return None @@ -243,19 +223,12 @@ def insert_node_in_tet_by_nodes( process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="insert_node_in_tet_by_nodes" ) - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) - if node3 is not None: - check_type(node3, EntList) - if node4 is not None: - check_type(node4, EntList) + result = self.mesh_editor.InsertNodeInTetByNodes( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(node3, "ent_list"), - coerce_optional_dispatch(node4, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(node3, EntList), + check_and_coerce_optional(node4, EntList), ) if result is None: return None @@ -272,12 +245,11 @@ def insert_node_on_beam(self, beam: EntList | None, num_div: int = 2) -> EntList Entlist of the new node. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="insert_node_on_beam") - if beam is not None: - check_type(beam, EntList) + check_type(num_div, int) check_is_non_negative(num_div) result = self.mesh_editor.InsertNodeOnBeam( - coerce_optional_dispatch(beam, "ent_list"), num_div + check_and_coerce_optional(beam, EntList), num_div ) if result is None: return None @@ -295,14 +267,11 @@ def move_nodes(self, nodes: EntList | None, vector: Vector | None, loc: bool) -> True if successful; False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_nodes") - if nodes is not None: - check_type(nodes, EntList) - if vector is not None: - check_type(vector, Vector) + check_type(loc, bool) return self.mesh_editor.MoveNodes( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(vector, "vector"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(vector, Vector), loc, ) @@ -322,16 +291,11 @@ def align_nodes( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="align_nodes") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) - if to_align is not None: - check_type(to_align, EntList) + return self.mesh_editor.AlignNodes( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(to_align, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(to_align, EntList), ) def smooth_nodes(self, nodes: EntList | None, feat: bool) -> bool: @@ -346,10 +310,9 @@ def smooth_nodes(self, nodes: EntList | None, feat: bool) -> bool: True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="smooth_nodes") - if nodes is not None: - check_type(nodes, EntList) + check_type(feat, bool) - return self.mesh_editor.SmoothNodes(coerce_optional_dispatch(nodes, "ent_list"), feat) + return self.mesh_editor.SmoothNodes(check_and_coerce_optional(nodes, EntList), feat) def orient(self, fusion: bool) -> bool: """ @@ -377,9 +340,8 @@ def flip_normals(self, tris: EntList | None) -> bool: True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="flip_normals") - if tris is not None: - check_type(tris, EntList) - return self.mesh_editor.FlipNormals(coerce_optional_dispatch(tris, "ent_list")) + + return self.mesh_editor.FlipNormals(check_and_coerce_optional(tris, EntList)) def align_normals(self, seed_tri: EntList | None, tris: EntList | None) -> int: """ @@ -394,13 +356,9 @@ def align_normals(self, seed_tri: EntList | None, tris: EntList | None) -> int: Number of triangles whose normals were aligned """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="align_normals") - if seed_tri is not None: - check_type(seed_tri, EntList) - if tris is not None: - check_type(tris, EntList) + return self.mesh_editor.AlignNormals( - coerce_optional_dispatch(seed_tri, "ent_list"), - coerce_optional_dispatch(tris, "ent_list"), + check_and_coerce_optional(seed_tri, EntList), check_and_coerce_optional(tris, EntList) ) def fill_hole(self, nodes: EntList | None, fill_type: int | None = None) -> bool: @@ -417,12 +375,11 @@ def fill_hole(self, nodes: EntList | None, fill_type: int | None = None) -> bool True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="fill_hole") - if nodes is not None: - check_type(nodes, EntList) + if fill_type is None: - return self.mesh_editor.FillHole(coerce_optional_dispatch(nodes, "ent_list")) + return self.mesh_editor.FillHole(check_and_coerce_optional(nodes, EntList)) check_type(fill_type, int) - return self.mesh_editor.FillHole2(coerce_optional_dispatch(nodes, "ent_list"), fill_type) + return self.mesh_editor.FillHole2(check_and_coerce_optional(nodes, EntList), fill_type) # pylint: disable-next=R0913, R0917 def create_tet( @@ -447,22 +404,13 @@ def create_tet( The new tetrahedron. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_tet") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) - if node3 is not None: - check_type(node3, EntList) - if node4 is not None: - check_type(node4, EntList) - if prop is not None: - check_type(prop, Property) - prop_disp = coerce_optional_dispatch(prop, "prop") + + prop_disp = check_and_coerce_optional(prop, Property) result = self.mesh_editor.CreateTet( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(node3, "ent_list"), - coerce_optional_dispatch(node4, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(node3, EntList), + check_and_coerce_optional(node4, EntList), prop_disp, ) if result is None: @@ -489,19 +437,12 @@ def create_tri( The new triangle """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_tri") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) - if node3 is not None: - check_type(node3, EntList) - if prop is not None: - check_type(prop, Property) - prop_disp = coerce_optional_dispatch(prop, "prop") + + prop_disp = check_and_coerce_optional(prop, Property) result = self.mesh_editor.CreateTri( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(node3, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(node3, EntList), prop_disp, ) if result is None: @@ -557,15 +498,14 @@ def refine_tetras_by_labels( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="refine_tetras_by_labels") - if nodes is not None: - check_type(nodes, EntList) + check_type(num_layer, int) check_is_non_negative(num_layer) check_type(isolate_refined_tet, bool) check_type(refine_surface, bool) check_type(surface_edge_length, (int, float)) return self.mesh_editor.RefineTetrasByLabels( - coerce_optional_dispatch(nodes, "ent_list"), + check_and_coerce_optional(nodes, EntList), num_layer, isolate_refined_tet, refine_surface, @@ -599,28 +539,15 @@ def create_wedge( The new wedge. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_wedge") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) - if node3 is not None: - check_type(node3, EntList) - if node4 is not None: - check_type(node4, EntList) - if node5 is not None: - check_type(node5, EntList) - if node6 is not None: - check_type(node6, EntList) - if prop is not None: - check_type(prop, Property) + result = self.mesh_editor.CreateWedge( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), - coerce_optional_dispatch(node3, "ent_list"), - coerce_optional_dispatch(node4, "ent_list"), - coerce_optional_dispatch(node5, "ent_list"), - coerce_optional_dispatch(node6, "ent_list"), - coerce_optional_dispatch(prop, "prop"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), + check_and_coerce_optional(node3, EntList), + check_and_coerce_optional(node4, EntList), + check_and_coerce_optional(node5, EntList), + check_and_coerce_optional(node6, EntList), + check_and_coerce_optional(prop, Property), ) if result is None: @@ -639,12 +566,11 @@ def convert_wedges_to_tetras(self, wedges: EntList | None, num_layer: int) -> bo True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="convert_wedges_to_tetras") - if wedges is not None: - check_type(wedges, EntList) + check_type(num_layer, int) check_is_non_negative(num_layer) return self.mesh_editor.ConvertWedgesToTetras( - coerce_optional_dispatch(wedges, "ent_list"), num_layer + check_and_coerce_optional(wedges, EntList), num_layer ) def create_beams( @@ -663,19 +589,15 @@ def create_beams( The new beam. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_beams") - if node1 is not None: - check_type(node1, EntList) - if node2 is not None: - check_type(node2, EntList) + check_type(num_beams, int) check_is_non_negative(num_beams) - if prop is not None: - check_type(prop, Property) + result = self.mesh_editor.CreateBeams( - coerce_optional_dispatch(node1, "ent_list"), - coerce_optional_dispatch(node2, "ent_list"), + check_and_coerce_optional(node1, EntList), + check_and_coerce_optional(node2, EntList), num_beams, - coerce_optional_dispatch(prop, "prop"), + check_and_coerce_optional(prop, Property), ) if result is None: @@ -715,9 +637,8 @@ def delete(self, entities: EntList | None) -> EntList: You would need to delete the dependent entities first """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="delete") - if entities is not None: - check_type(entities, EntList) - result = self.mesh_editor.Delete(coerce_optional_dispatch(entities, "ent_list")) + + result = self.mesh_editor.Delete(check_and_coerce_optional(entities, EntList)) if result is None: return None return EntList(result) @@ -738,14 +659,13 @@ def remesh_area( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="remesh_area") - if tris is not None: - check_type(tris, EntList) + check_type(size, (int, float)) check_type(imprint, bool) check_type(smooth, (int, float)) check_range(smooth, 0.0, 1.0, True, True) return self.mesh_editor.RemeshArea2( - coerce_optional_dispatch(tris, "ent_list"), size, imprint, smooth + check_and_coerce_optional(tris, EntList), size, imprint, smooth ) def match_nodes(self, nodes: EntList | None, tris: EntList | None, layer: str) -> int: @@ -762,14 +682,11 @@ def match_nodes(self, nodes: EntList | None, tris: EntList | None, layer: str) - Number of nodes affected """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="match_notes") - if nodes is not None: - check_type(nodes, EntList) - if tris is not None: - check_type(tris, EntList) + check_type(layer, str) return self.mesh_editor.MatchNodes( - coerce_optional_dispatch(nodes, "ent_list"), - coerce_optional_dispatch(tris, "ent_list"), + check_and_coerce_optional(nodes, EntList), + check_and_coerce_optional(tris, EntList), layer, ) @@ -793,10 +710,10 @@ def make_region( check_type(tol, float) check_type(is_angular, bool) check_type(mesh, bool) + if prop is not None: - check_type(prop, Property) return self.mesh_editor.MakeRegion2( - tol, is_angular, mesh, coerce_optional_dispatch(prop, "prop") + tol, is_angular, mesh, check_and_coerce_optional(prop, Property) ) return self.mesh_editor.MakeRegion(tol, is_angular) @@ -812,13 +729,10 @@ def move_beam_node(self, moving_node: EntList | None, target: Vector | None) -> True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_beam_node") - if moving_node is not None: - check_type(moving_node, EntList) - if target is not None: - check_type(target, Vector) + return self.mesh_editor.MoveBeamNode( - coerce_optional_dispatch(moving_node, "ent_list"), - coerce_optional_dispatch(target, "vector"), + check_and_coerce_optional(moving_node, EntList), + check_and_coerce_optional(target, Vector), ) def move_node_to_edge( @@ -842,18 +756,13 @@ def move_node_to_edge( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="move_node_to_edge") - if node is not None: - check_type(node, EntList) - if edge_node1 is not None: - check_type(edge_node1, EntList) - if edge_node2 is not None: - check_type(edge_node2, EntList) + check_type(param_loc, (int, float)) check_range(param_loc, 0.0, 1.0, True, True) return self.mesh_editor.MoveNodeToEdge( - coerce_optional_dispatch(node, "ent_list"), - coerce_optional_dispatch(edge_node1, "ent_list"), - coerce_optional_dispatch(edge_node2, "ent_list"), + check_and_coerce_optional(node, EntList), + check_and_coerce_optional(edge_node1, EntList), + check_and_coerce_optional(edge_node2, EntList), param_loc, ) @@ -873,19 +782,15 @@ def create_beams_by_points( The new beam. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_beams_by_points") - if pt1 is not None: - check_type(pt1, Vector) - if pt2 is not None: - check_type(pt2, Vector) + check_type(num, int) check_is_non_negative(num) - if prop is not None: - check_type(prop, Property) + result = self.mesh_editor.CreateBeamsByPoints( - coerce_optional_dispatch(pt1, "vector"), - coerce_optional_dispatch(pt2, "vector"), + check_and_coerce_optional(pt1, Vector), + check_and_coerce_optional(pt2, Vector), num, - coerce_optional_dispatch(prop, "prop"), + check_and_coerce_optional(prop, Property), ) if result is None: return None @@ -902,9 +807,8 @@ def project_mesh(self, tris: EntList | None) -> bool: True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="project_mesh") - if tris is not None: - check_type(tris, EntList) - return self.mesh_editor.ProjectMesh(coerce_optional_dispatch(tris, "ent_list")) + + return self.mesh_editor.ProjectMesh(check_and_coerce_optional(tris, EntList)) def convert_to_beams( self, start_node: EntList | None, prop: Property | None, junction: bool, num_branch: int @@ -922,16 +826,13 @@ def convert_to_beams( Number of beams created """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="convert_to_beams") - if start_node is not None: - check_type(start_node, EntList) - if prop is not None: - check_type(prop, Property) + check_type(junction, bool) check_type(num_branch, int) check_is_non_negative(num_branch) return self.mesh_editor.ConvertToBeams( - coerce_optional_dispatch(start_node, "ent_list"), - coerce_optional_dispatch(prop, "prop"), + check_and_coerce_optional(start_node, EntList), + check_and_coerce_optional(prop, Property), junction, num_branch, ) @@ -986,15 +887,12 @@ def cut_triangles_by_plane( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="cut_triangles_by_plane") - if plane_normal is not None: - check_type(plane_normal, Vector) - if ref_point is not None: - check_type(ref_point, Vector) + check_type(fill, bool) check_type(smooth, bool) return self.mesh_editor.CutTrianglesByPlane( - coerce_optional_dispatch(plane_normal, "vector"), - coerce_optional_dispatch(ref_point, "vector"), + check_and_coerce_optional(plane_normal, Vector), + check_and_coerce_optional(ref_point, Vector), fill, smooth, ) @@ -1015,13 +913,12 @@ def offset_triangles( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="offset_triangles") - if offset_tri is not None: - check_type(offset_tri, EntList) + check_type(offset_dist, (int, float)) check_type(falloff_dist, (int, float)) check_type(smooth_nb, bool) return self.mesh_editor.OffsetTriangles( - coerce_optional_dispatch(offset_tri, "ent_list"), offset_dist, falloff_dist, smooth_nb + check_and_coerce_optional(offset_tri, EntList), offset_dist, falloff_dist, smooth_nb ) # pylint: disable-next=R0913, R0917 @@ -1049,21 +946,19 @@ def extrude_triangles( True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="extrude_triangles") - if offset_tri is not None: - check_type(offset_tri, EntList) + check_type(dist, (int, float)) check_type(scale, (int, float)) check_type(smooth_nb, bool) check_type(create_new_body, bool) - if prop is not None: - check_type(prop, Property) + return self.mesh_editor.ExtrudeTriangles( - coerce_optional_dispatch(offset_tri, "ent_list"), + check_and_coerce_optional(offset_tri, EntList), dist, scale, smooth_nb, create_new_body, - coerce_optional_dispatch(prop, "prop"), + check_and_coerce_optional(prop, Property), ) def imprint_visible_triangles(self) -> bool: @@ -1087,9 +982,8 @@ def imprint_selected_triangles(self, tri: EntList | None) -> bool: True if operation is successful; False otherwise """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="imprint_selected_triangles") - if tri is not None: - check_type(tri, EntList) - return self.mesh_editor.ImprintSelectedTriangles(coerce_optional_dispatch(tri, "ent_list")) + + return self.mesh_editor.ImprintSelectedTriangles(check_and_coerce_optional(tri, EntList)) # pylint: disable=R0913, R0917 def global_merge( @@ -1148,15 +1042,12 @@ def merge_nodes( number of nodes merged """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="merge_nodes") - if target is not None: - check_type(target, EntList) - if nodes is not None: - check_type(nodes, EntList) + check_type(fusion, bool) check_type(use_mid, bool) return self.mesh_editor.MergeNodes2( - coerce_optional_dispatch(target, "ent_list"), - coerce_optional_dispatch(nodes, "ent_list"), + check_and_coerce_optional(target, EntList), + check_and_coerce_optional(nodes, EntList), fusion, use_mid, ) diff --git a/src/moldflow/message_box.py b/src/moldflow/message_box.py index 0817a51..b4b831e 100644 --- a/src/moldflow/message_box.py +++ b/src/moldflow/message_box.py @@ -62,7 +62,6 @@ # pylint: disable=invalid-name INT_PTR = ctypes.c_ssize_t - # Win32 MessageBox flags (from winuser.h) WIN_MB_OK = 0x00000000 WIN_MB_OKCANCEL = 0x00000001 diff --git a/src/moldflow/modeler.py b/src/moldflow/modeler.py index 76f62da..7213d84 100644 --- a/src/moldflow/modeler.py +++ b/src/moldflow/modeler.py @@ -14,8 +14,8 @@ check_is_non_negative, check_is_positive, check_type, + check_and_coerce_optional, get_enum_value, - coerce_optional_dispatch, ) from .com_proxy import safe_com from .boundary_list import BoundaryList @@ -51,9 +51,8 @@ def create_node_by_xyz(self, coord: Vector | None) -> EntList: int: The ID of the created node. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_node_by_xyz") - if coord is not None: - check_type(coord, Vector) - result = self.modeler.CreateNodeByXYZ(coerce_optional_dispatch(coord, "vector")) + + result = self.modeler.CreateNodeByXYZ(check_and_coerce_optional(coord, Vector)) if result is None: return None return EntList(result) @@ -73,15 +72,12 @@ def create_nodes_between( EntList: The list of created nodes. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_nodes_between") - if start is not None: - check_type(start, Vector) - if end is not None: - check_type(end, Vector) + check_type(num_nodes, int) check_is_positive(num_nodes) result = self.modeler.CreateNodesBetween( - coerce_optional_dispatch(start, "vector"), - coerce_optional_dispatch(end, "vector"), + check_and_coerce_optional(start, Vector), + check_and_coerce_optional(end, Vector), num_nodes, ) if result is None: @@ -103,15 +99,12 @@ def create_nodes_by_offset( EntList: The list of created nodes. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_nodes_by_offset") - if coord is not None: - check_type(coord, Vector) - if offset is not None: - check_type(offset, Vector) + check_type(num_nodes, int) check_is_positive(num_nodes) result = self.modeler.CreateNodesByOffset( - coerce_optional_dispatch(coord, "vector"), - coerce_optional_dispatch(offset, "vector"), + check_and_coerce_optional(coord, Vector), + check_and_coerce_optional(offset, Vector), num_nodes, ) if result is None: @@ -131,13 +124,12 @@ def create_nodes_by_divide(self, curve: EntList | None, num_nodes: int, ends: bo EntList: The list of created nodes. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_nodes_by_divide") - if curve is not None: - check_type(curve, EntList) + check_type(num_nodes, int) check_is_positive(num_nodes) check_type(ends, bool) result = self.modeler.CreateNodesByDivide( - coerce_optional_dispatch(curve, "ent_list"), num_nodes, ends + check_and_coerce_optional(curve, EntList), num_nodes, ends ) if result is None: return None @@ -171,16 +163,11 @@ def create_node_by_intersect( EntList: The list of created nodes. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_node_by_intersect") - if curve is not None: - check_type(curve, EntList) - if curve2 is not None: - check_type(curve2, EntList) - if pt is not None: - check_type(pt, Vector) + result = self.modeler.CreateNodeByIntersect( - coerce_optional_dispatch(curve, "ent_list"), - coerce_optional_dispatch(curve2, "ent_list"), - coerce_optional_dispatch(pt, "vector"), + check_and_coerce_optional(curve, EntList), + check_and_coerce_optional(curve2, EntList), + check_and_coerce_optional(pt, Vector), ) if result is None: return None @@ -210,18 +197,14 @@ def create_line( EntList: The list of created lines. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_line") - if coord is not None: - check_type(coord, Vector) - if vec is not None: - check_type(vec, Vector) + check_type(relative, bool) - if prop_set is not None: - check_type(prop_set, Property) + check_type(ends, bool) - prop_disp = coerce_optional_dispatch(prop_set, "prop") + prop_disp = check_and_coerce_optional(prop_set, Property) result = self.modeler.CreateLine( - coerce_optional_dispatch(coord, "vector"), - coerce_optional_dispatch(vec, "vector"), + check_and_coerce_optional(coord, Vector), + check_and_coerce_optional(vec, Vector), relative, prop_disp, ends, @@ -255,21 +238,19 @@ def create_arc_by_angle( EntList: The list of created arcs. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_arc_by_angle") - if center is not None: - check_type(center, Vector) + check_type(radius, (int, float)) check_is_positive(radius) check_type(start, (int, float)) check_type(end, (int, float)) - if prop_set is not None: - check_type(prop_set, Property) + check_type(ends, bool) result = self.modeler.CreateArcByAngle( - coerce_optional_dispatch(center, "vector"), + check_and_coerce_optional(center, Vector), radius, start, end, - coerce_optional_dispatch(prop_set, "prop"), + check_and_coerce_optional(prop_set, Property), ends, ) if result is None: @@ -302,22 +283,16 @@ def create_arc_by_points( EntList: The list of created arcs. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_arc_by_points") - if pt1 is not None: - check_type(pt1, Vector) - if pt2 is not None: - check_type(pt2, Vector) - if pt3 is not None: - check_type(pt3, Vector) + check_type(circle, bool) - if prop_set is not None: - check_type(prop_set, Property) + check_type(ends, bool) result = self.modeler.CreateArcByPoints( - coerce_optional_dispatch(pt1, "vector"), - coerce_optional_dispatch(pt2, "vector"), - coerce_optional_dispatch(pt3, "vector"), + check_and_coerce_optional(pt1, Vector), + check_and_coerce_optional(pt2, Vector), + check_and_coerce_optional(pt3, Vector), circle, - coerce_optional_dispatch(prop_set, "prop"), + check_and_coerce_optional(prop_set, Property), ends, ) # pylint: disable=R0801 @@ -373,22 +348,19 @@ def create_curve_by_connect( EntList: The list of created curves. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_curve_by_connect") - if curve1 is not None: - check_type(curve1, EntList) + end1 = get_enum_value(end1, CurveInitPosition) - if curve2 is not None: - check_type(curve2, EntList) + end2 = get_enum_value(end2, CurveInitPosition) check_type(factor, (int, float)) - if prop_set is not None: - check_type(prop_set, Property) + result = self.modeler.CreateCurveByConnect( - coerce_optional_dispatch(curve1, "ent_list"), + check_and_coerce_optional(curve1, EntList), end1, - coerce_optional_dispatch(curve2, "ent_list"), + check_and_coerce_optional(curve2, EntList), end2, factor, - coerce_optional_dispatch(prop_set, "prop"), + check_and_coerce_optional(prop_set, Property), ) if result is None: return None @@ -409,14 +381,11 @@ def create_spline( EntList: The list of created splines. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_spline") - if coord is not None: - check_type(coord, VectorArray) - if prop_set is not None: - check_type(prop_set, Property) + check_type(ends, bool) result = self.modeler.CreateSpline( - coerce_optional_dispatch(coord, "vector_array"), - coerce_optional_dispatch(prop_set, "prop"), + check_and_coerce_optional(coord, VectorArray), + check_and_coerce_optional(prop_set, Property), ends, ) if result is None: @@ -435,13 +404,9 @@ def break_curves(self, curve1: EntList | None, curve2: EntList | None) -> bool: bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="break_curves") - if curve1 is not None: - check_type(curve1, EntList) - if curve2 is not None: - check_type(curve2, EntList) + return self.modeler.BreakCurves( - coerce_optional_dispatch(curve1, "ent_list"), - coerce_optional_dispatch(curve2, "ent_list"), + check_and_coerce_optional(curve1, EntList), check_and_coerce_optional(curve2, EntList) ) def set_property(self, ents: EntList | None, prop_set: Property | None) -> bool: @@ -456,12 +421,9 @@ def set_property(self, ents: EntList | None, prop_set: Property | None) -> bool: bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_property") - if ents is not None: - check_type(ents, EntList) - if prop_set is not None: - check_type(prop_set, Property) + return self.modeler.SetProperty( - coerce_optional_dispatch(ents, "ent_list"), coerce_optional_dispatch(prop_set, "prop") + check_and_coerce_optional(ents, EntList), check_and_coerce_optional(prop_set, Property) ) def create_region_by_boundary( @@ -478,12 +440,9 @@ def create_region_by_boundary( EntList: The list of created regions. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_region_by_boundary") - if curve is not None: - check_type(curve, EntList) - if prop_set is not None: - check_type(prop_set, Property) + result = self.modeler.CreateRegionByBoundary( - coerce_optional_dispatch(curve, "ent_list"), coerce_optional_dispatch(prop_set, "prop") + check_and_coerce_optional(curve, EntList), check_and_coerce_optional(prop_set, Property) ) if result is None: return None @@ -501,12 +460,9 @@ def create_region_by_nodes(self, nodes: EntList | None, prop_set: Property | Non EntList: The list of created regions. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_region_by_nodes") - if nodes is not None: - check_type(nodes, EntList) - if prop_set is not None: - check_type(prop_set, Property) + result = self.modeler.CreateRegionByNodes( - coerce_optional_dispatch(nodes, "ent_list"), coerce_optional_dispatch(prop_set, "prop") + check_and_coerce_optional(nodes, EntList), check_and_coerce_optional(prop_set, Property) ) if result is None: return None @@ -527,16 +483,11 @@ def create_region_by_ruling( EntList: The list of created regions. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_region_by_ruling") - if curve1 is not None: - check_type(curve1, EntList) - if curve2 is not None: - check_type(curve2, EntList) - if prop_set is not None: - check_type(prop_set, Property) + result = self.modeler.CreateRegionByRuling( - coerce_optional_dispatch(curve1, "ent_list"), - coerce_optional_dispatch(curve2, "ent_list"), - coerce_optional_dispatch(prop_set, "prop"), + check_and_coerce_optional(curve1, EntList), + check_and_coerce_optional(curve2, EntList), + check_and_coerce_optional(prop_set, Property), ) if result is None: return None @@ -557,16 +508,11 @@ def create_region_by_extrusion( EntList: The list of created regions. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_region_by_extrusion") - if curve is not None: - check_type(curve, EntList) - if direction is not None: - check_type(direction, Vector) - if prop_set is not None: - check_type(prop_set, Property) + result = self.modeler.CreateRegionByExtrusion( - coerce_optional_dispatch(curve, "ent_list"), - coerce_optional_dispatch(direction, "vector"), - coerce_optional_dispatch(prop_set, "prop"), + check_and_coerce_optional(curve, EntList), + check_and_coerce_optional(direction, Vector), + check_and_coerce_optional(prop_set, Property), ) if result is None: return None @@ -584,13 +530,9 @@ def create_hole_by_boundary(self, region: EntList | None, curve: EntList | None) bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_hole_by_boundary") - if region is not None: - check_type(region, EntList) - if curve is not None: - check_type(curve, EntList) + return self.modeler.CreateHoleByBoundary( - coerce_optional_dispatch(region, "ent_list"), - coerce_optional_dispatch(curve, "ent_list"), + check_and_coerce_optional(region, EntList), check_and_coerce_optional(curve, EntList) ) def create_hole_by_nodes(self, region: EntList | None, nodes: EntList | None) -> bool: @@ -605,13 +547,9 @@ def create_hole_by_nodes(self, region: EntList | None, nodes: EntList | None) -> bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_hole_by_nodes") - if region is not None: - check_type(region, EntList) - if nodes is not None: - check_type(nodes, EntList) + return self.modeler.CreateHoleByNodes( - coerce_optional_dispatch(region, "ent_list"), - coerce_optional_dispatch(nodes, "ent_list"), + check_and_coerce_optional(region, EntList), check_and_coerce_optional(nodes, EntList) ) def create_hole_by_ruling( @@ -629,16 +567,11 @@ def create_hole_by_ruling( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_hole_by_ruling") - if region is not None: - check_type(region, EntList) - if curve1 is not None: - check_type(curve1, EntList) - if curve2 is not None: - check_type(curve2, EntList) + return self.modeler.CreateHoleByRuling( - coerce_optional_dispatch(region, "ent_list"), - coerce_optional_dispatch(curve1, "ent_list"), - coerce_optional_dispatch(curve2, "ent_list"), + check_and_coerce_optional(region, EntList), + check_and_coerce_optional(curve1, EntList), + check_and_coerce_optional(curve2, EntList), ) def create_hole_by_extrusion( @@ -656,16 +589,11 @@ def create_hole_by_extrusion( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_hole_by_extrusion") - if region is not None: - check_type(region, EntList) - if curve is not None: - check_type(curve, EntList) - if direction is not None: - check_type(direction, Vector) + return self.modeler.CreateHoleByExtrusion( - coerce_optional_dispatch(region, "ent_list"), - coerce_optional_dispatch(curve, "ent_list"), - coerce_optional_dispatch(direction, "vector"), + check_and_coerce_optional(region, EntList), + check_and_coerce_optional(curve, EntList), + check_and_coerce_optional(direction, Vector), ) # pylint: disable=R0913, R0917 @@ -691,18 +619,13 @@ def reflect( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="reflect") - if ent is not None: - check_type(ent, EntList) - if reference is not None: - check_type(reference, Vector) - if plane is not None: - check_type(plane, Vector) + check_type(copy, bool) check_type(merge, bool) return self.modeler.Reflect( - coerce_optional_dispatch(ent, "ent_list"), - coerce_optional_dispatch(reference, "vector"), - coerce_optional_dispatch(plane, "vector"), + check_and_coerce_optional(ent, EntList), + check_and_coerce_optional(reference, Vector), + check_and_coerce_optional(plane, Vector), copy, merge, ) @@ -731,18 +654,13 @@ def scale( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="scale") - if ent is not None: - check_type(ent, EntList) - if reference is not None: - check_type(reference, Vector) - if scale is not None: - check_type(scale, Vector) + check_type(copy, bool) check_type(merge, bool) return self.modeler.Scale( - coerce_optional_dispatch(ent, "ent_list"), - coerce_optional_dispatch(reference, "vector"), - coerce_optional_dispatch(scale, "vector"), + check_and_coerce_optional(ent, EntList), + check_and_coerce_optional(reference, Vector), + check_and_coerce_optional(scale, Vector), copy, merge, ) @@ -771,17 +689,14 @@ def translate( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="translate") - if ent is not None: - check_type(ent, EntList) - if translation is not None: - check_type(translation, Vector) + check_type(copy, bool) check_type(num_copies, int) check_is_non_negative(num_copies) check_type(merge, bool) return self.modeler.Translate( - coerce_optional_dispatch(ent, "ent_list"), - coerce_optional_dispatch(translation, "vector"), + check_and_coerce_optional(ent, EntList), + check_and_coerce_optional(translation, Vector), copy, num_copies, merge, @@ -815,12 +730,7 @@ def rotate( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="rotate") - if ent is not None: - check_type(ent, EntList) - if center is not None: - check_type(center, Vector) - if axis is not None: - check_type(axis, Vector) + check_type(angle, (int, float)) check_is_non_negative(angle) check_type(copy, bool) @@ -828,9 +738,9 @@ def rotate( check_is_non_negative(num_copies) check_type(merge, bool) return self.modeler.Rotate( - coerce_optional_dispatch(ent, "ent_list"), - coerce_optional_dispatch(center, "vector"), - coerce_optional_dispatch(axis, "vector"), + check_and_coerce_optional(ent, EntList), + check_and_coerce_optional(center, Vector), + check_and_coerce_optional(axis, Vector), angle, copy, num_copies, @@ -863,21 +773,14 @@ def rotate_3_pts( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="rotate_3_pts") - if ents is not None: - check_type(ents, EntList) - if pt1 is not None: - check_type(pt1, Vector) - if pt2 is not None: - check_type(pt2, Vector) - if pt3 is not None: - check_type(pt3, Vector) + check_type(copy, bool) check_type(merge, bool) return self.modeler.Rotate3Pts( - coerce_optional_dispatch(ents, "ent_list"), - coerce_optional_dispatch(pt1, "vector"), - coerce_optional_dispatch(pt2, "vector"), - coerce_optional_dispatch(pt3, "vector"), + check_and_coerce_optional(ents, EntList), + check_and_coerce_optional(pt1, Vector), + check_and_coerce_optional(pt2, Vector), + check_and_coerce_optional(pt3, Vector), copy, merge, ) @@ -897,16 +800,11 @@ def create_lcs_by_points( EntList: The created local coordinate system. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_lcs_by_points") - if coord1 is not None: - check_type(coord1, Vector) - if coord2 is not None: - check_type(coord2, Vector) - if coord3 is not None: - check_type(coord3, Vector) + result = self.modeler.CreateLCSByPoints( - coerce_optional_dispatch(coord1, "vector"), - coerce_optional_dispatch(coord2, "vector"), - coerce_optional_dispatch(coord3, "vector"), + check_and_coerce_optional(coord1, Vector), + check_and_coerce_optional(coord2, Vector), + check_and_coerce_optional(coord3, Vector), ) if result is None: return None @@ -926,11 +824,10 @@ def activate_lcs(self, lcs: EntList | None, active: bool, lcs_type: LCSType | st bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="activate_lcs") - if lcs is not None: - check_type(lcs, EntList) + check_type(active, bool) lcs_type = get_enum_value(lcs_type, LCSType) - return self.modeler.ActivateLCS(coerce_optional_dispatch(lcs, "ent_list"), active, lcs_type) + return self.modeler.ActivateLCS(check_and_coerce_optional(lcs, EntList), active, lcs_type) def create_boundary_list(self) -> BoundaryList: """ @@ -972,22 +869,18 @@ def set_mesh_size( process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_mesh_size") check_type(global_size, (int, float)) check_is_non_negative(global_size) - if ents is not None: - check_type(ents, EntList) - if boundaries is not None: - check_type(boundaries, BoundaryList) + check_type(size, (int, float)) check_is_positive(size) - if cad_bodies is not None: - check_type(cad_bodies, EntList) + check_type(num_layer, int) check_is_non_negative(num_layer) return self.modeler.SetMeshSize2( global_size, - coerce_optional_dispatch(ents, "ent_list"), - coerce_optional_dispatch(boundaries, "boundary_list"), + check_and_coerce_optional(ents, EntList), + check_and_coerce_optional(boundaries, BoundaryList), size, - coerce_optional_dispatch(cad_bodies, "ent_list"), + check_and_coerce_optional(cad_bodies, EntList), num_layer, ) @@ -1006,15 +899,12 @@ def scale_mesh_density( bool: True if the operation was successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="scale_mesh_density") - if ents is not None: - check_type(ents, EntList) - if boundaries is not None: - check_type(boundaries, BoundaryList) + check_type(scale, (int, float)) check_is_positive(scale) return self.modeler.ScaleMeshDensity( - coerce_optional_dispatch(ents, "ent_list"), - coerce_optional_dispatch(boundaries, "boundary_list"), + check_and_coerce_optional(ents, EntList), + check_and_coerce_optional(boundaries, BoundaryList), scale, ) @@ -1031,9 +921,8 @@ def modified_with_inventor_fusion(self, ents: EntList | None) -> int: process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="modified_with_inventor_fusion" ) - if ents is not None: - check_type(ents, EntList) - return self.modeler.ModifiedWithInventorFusion(coerce_optional_dispatch(ents, "ent_list")) + + return self.modeler.ModifiedWithInventorFusion(check_and_coerce_optional(ents, EntList)) def is_inventor_fusion_cad_edit_done(self, job_id: int) -> bool: """ diff --git a/src/moldflow/mold_surface_generator.py b/src/moldflow/mold_surface_generator.py index 18374cd..d08c82a 100644 --- a/src/moldflow/mold_surface_generator.py +++ b/src/moldflow/mold_surface_generator.py @@ -7,7 +7,7 @@ """ from .logger import process_log, LogMessage -from .helper import check_type, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional from .com_proxy import safe_com from .vector import Vector @@ -85,9 +85,8 @@ def origin(self, value: Vector | None) -> None: value (Vector): The new origin of the mold surface. """ process_log(__name__, LogMessage.PROPERTY_SET, locals(), name="origin", value=value) - if value is not None: - check_type(value, Vector) - self.mold_surface_generator.Origin = coerce_optional_dispatch(value, "vector") + + self.mold_surface_generator.Origin = check_and_coerce_optional(value, Vector) @property def dimensions(self) -> Vector: @@ -113,9 +112,8 @@ def dimensions(self, value: Vector | None) -> None: value (Vector): The new dimensions of the mold surface. """ process_log(__name__, LogMessage.PROPERTY_SET, locals(), name="dimensions", value=value) - if value is not None: - check_type(value, Vector) - self.mold_surface_generator.Dimensions = coerce_optional_dispatch(value, "vector") + + self.mold_surface_generator.Dimensions = check_and_coerce_optional(value, Vector) @property def save_as_cad(self) -> bool: diff --git a/src/moldflow/plot.py b/src/moldflow/plot.py index 0cdbf24..10fd6fd 100644 --- a/src/moldflow/plot.py +++ b/src/moldflow/plot.py @@ -11,12 +11,12 @@ from .logger import process_log, LogMessage from .helper import ( check_type, + check_and_coerce_optional, get_enum_value, check_range, check_is_non_negative, check_expected_values, check_file_extension, - coerce_optional_dispatch, ) from .common import ( DisplayComponent, @@ -1072,9 +1072,8 @@ def add_xy_plot_curve(self, curve: EntList | None) -> None: curve (EntList): The curve to add. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_xy_plot_curve") - if curve is not None: - check_type(curve, EntList) - self.plot.AddXYPlotCurve(coerce_optional_dispatch(curve, "ent_list")) + + self.plot.AddXYPlotCurve(check_and_coerce_optional(curve, EntList)) def delete_xy_plot_curve(self, curve: EntList | None) -> None: """ @@ -1084,9 +1083,8 @@ def delete_xy_plot_curve(self, curve: EntList | None) -> None: curve (EntList): The curve to delete. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="delete_xy_plot_curve") - if curve is not None: - check_type(curve, EntList) - self.plot.DeleteXYPlotCurve(coerce_optional_dispatch(curve, "ent_list")) + + self.plot.DeleteXYPlotCurve(check_and_coerce_optional(curve, EntList)) @property def edge_display(self) -> int: @@ -1166,9 +1164,8 @@ def apply_best_fit(self, nodes: EntList | None) -> bool: bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="apply_best_fit") - if nodes is not None: - check_type(nodes, EntList) - return self.plot.ApplyBestFit(coerce_optional_dispatch(nodes, "ent_list")) + + return self.plot.ApplyBestFit(check_and_coerce_optional(nodes, EntList)) @property def deflection_scale_factor(self) -> float: @@ -1348,10 +1345,9 @@ def warp_query_node(self, node_id: int, return_values: DoubleArray | None) -> bo process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="warp_query_node") check_type(node_id, int) check_is_non_negative(node_id) - if return_values is not None: - check_type(return_values, DoubleArray) + return self.plot.WarpQueryNode( - node_id, coerce_optional_dispatch(return_values, "double_array") + node_id, check_and_coerce_optional(return_values, DoubleArray) ) @property @@ -1384,14 +1380,11 @@ def get_probe_plot_probe_line( process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_probe_plot_probe_line") check_type(index, int) check_is_non_negative(index) - if start_pt is not None: - check_type(start_pt, Vector) - if end_pt is not None: - check_type(end_pt, Vector) + return self.plot.GetProbePlotProbeLine( index, - coerce_optional_dispatch(start_pt, "vector"), - coerce_optional_dispatch(end_pt, "vector"), + check_and_coerce_optional(start_pt, Vector), + check_and_coerce_optional(end_pt, Vector), ) def add_probe_plot_probe_line(self, start_pt: Vector | None, end_pt: Vector | None) -> bool: @@ -1406,12 +1399,9 @@ def add_probe_plot_probe_line(self, start_pt: Vector | None, end_pt: Vector | No bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_probe_plot_probe_line") - if start_pt is not None: - check_type(start_pt, Vector) - if end_pt is not None: - check_type(end_pt, Vector) + return self.plot.AddProbePlotProbeLine( - coerce_optional_dispatch(start_pt, "vector"), coerce_optional_dispatch(end_pt, "vector") + check_and_coerce_optional(start_pt, Vector), check_and_coerce_optional(end_pt, Vector) ) def set_probe_plot_probe_line( @@ -1431,14 +1421,11 @@ def set_probe_plot_probe_line( process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_probe_plot_probe_line") check_type(index, int) check_is_non_negative(index) - if start_pt is not None: - check_type(start_pt, Vector) - if end_pt is not None: - check_type(end_pt, Vector) + return self.plot.SetProbePlotProbeLine( index, - coerce_optional_dispatch(start_pt, "vector"), - coerce_optional_dispatch(end_pt, "vector"), + check_and_coerce_optional(start_pt, Vector), + check_and_coerce_optional(end_pt, Vector), ) @property @@ -1756,9 +1743,8 @@ def single_color(self, value: Vector | None) -> None: value (Vector): single color to set as RGB vector. """ process_log(__name__, LogMessage.PROPERTY_SET, locals(), name="single_color", value=value) - if value is not None: - check_type(value, Vector) - self.plot.SetSingleColor(coerce_optional_dispatch(value, "vector")) + + self.plot.SetSingleColor(check_and_coerce_optional(value, Vector)) def set_plot_nodes_from_string(self, nodes: str) -> None: """ @@ -1781,9 +1767,8 @@ def set_plot_nodes_from_ent_list(self, ent_list: EntList | None) -> None: process_log( __name__, LogMessage.FUNCTION_CALL, locals(), name="set_plot_nodes_from_ent_list" ) - if ent_list is not None: - check_type(ent_list, EntList) - self.plot.SetPlotNodesFromEntList(coerce_optional_dispatch(ent_list, "ent_list")) + + self.plot.SetPlotNodesFromEntList(check_and_coerce_optional(ent_list, EntList)) def add_probe_plane(self, normal: str, point: str) -> bool: """ @@ -2488,8 +2473,7 @@ def shrinkage_compensation_estimated_shrinkage(self, value: Vector | None) -> No name="shrinkage_compensation_estimated_shrinkage", value=value, ) - if value is not None: - check_type(value, Vector) + self.plot.SetShrinkageCompensationEstimatedShrinkage( - coerce_optional_dispatch(value, "vector") + check_and_coerce_optional(value, Vector) ) diff --git a/src/moldflow/plot_manager.py b/src/moldflow/plot_manager.py index 69e8c68..bd9f77e 100644 --- a/src/moldflow/plot_manager.py +++ b/src/moldflow/plot_manager.py @@ -16,7 +16,14 @@ from .material_plot import MaterialPlot from .user_plot import UserPlot from .common import MaterialDatabase, MaterialIndex, PlotType, SystemUnits -from .helper import check_type, get_enum_value, check_file_extension, coerce_optional_dispatch +from .helper import ( + check_type, + check_optional_type, + coerce_optional_dispatch, + check_and_coerce_optional, + get_enum_value, + check_file_extension, +) from .com_proxy import safe_com from .errors import raise_save_error from .constants import XML_FILE_EXT, SDZ_FILE_EXT, FBX_FILE_EXT, ELE_FILE_EXT @@ -61,8 +68,7 @@ def get_next_plot(self, plot: Plot | None) -> Plot: Plot: The next plot. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_plot") - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) result = self.plot_manager.GetNextPlot(coerce_optional_dispatch(plot, "plot")) if result is None: return None @@ -156,8 +162,7 @@ def delete_plot(self, plot: Plot | None) -> None: plot (Plot): The plot to delete. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="delete_plot") - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) self.plot_manager.DeletePlot(coerce_optional_dispatch(plot, "plot")) def data_has_xy_plot_by_ds_id(self, ds_id: int) -> bool: @@ -209,17 +214,12 @@ def get_scalar_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_scalar_data") check_type(ds_id, int) - if indp_values is not None: - check_type(indp_values, DoubleArray) - if ent_ids is not None: - check_type(ent_ids, IntegerArray) - if scalar_data is not None: - check_type(scalar_data, DoubleArray) + return self.plot_manager.GetScalarData( ds_id, - coerce_optional_dispatch(indp_values, "double_array"), - coerce_optional_dispatch(ent_ids, "integer_array"), - coerce_optional_dispatch(scalar_data, "double_array"), + check_and_coerce_optional(indp_values, DoubleArray), + check_and_coerce_optional(ent_ids, IntegerArray), + check_and_coerce_optional(scalar_data, DoubleArray), ) # pylint: disable-next=R0913, R0917 @@ -248,23 +248,14 @@ def get_vector_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_vector_data") check_type(ds_id, int) - if indp_values is not None: - check_type(indp_values, DoubleArray) - if ent_ids is not None: - check_type(ent_ids, IntegerArray) - if va is not None: - check_type(va, DoubleArray) - if vb is not None: - check_type(vb, DoubleArray) - if vc is not None: - check_type(vc, DoubleArray) + return self.plot_manager.GetVectorData( ds_id, - coerce_optional_dispatch(indp_values, "double_array"), - coerce_optional_dispatch(ent_ids, "integer_array"), - coerce_optional_dispatch(va, "double_array"), - coerce_optional_dispatch(vb, "double_array"), - coerce_optional_dispatch(vc, "double_array"), + check_and_coerce_optional(indp_values, DoubleArray), + check_and_coerce_optional(ent_ids, IntegerArray), + check_and_coerce_optional(va, DoubleArray), + check_and_coerce_optional(vb, DoubleArray), + check_and_coerce_optional(vc, DoubleArray), ) # pylint: disable-next=R0913, R0917 @@ -299,32 +290,17 @@ def get_tensor_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_tensor_data") check_type(ds_id, int) - if indp_values is not None: - check_type(indp_values, DoubleArray) - if ent_ids is not None: - check_type(ent_ids, IntegerArray) - if t11 is not None: - check_type(t11, DoubleArray) - if t22 is not None: - check_type(t22, DoubleArray) - if t33 is not None: - check_type(t33, DoubleArray) - if t12 is not None: - check_type(t12, DoubleArray) - if t13 is not None: - check_type(t13, DoubleArray) - if t23 is not None: - check_type(t23, DoubleArray) + return self.plot_manager.GetTensorData( ds_id, - coerce_optional_dispatch(indp_values, "double_array"), - coerce_optional_dispatch(ent_ids, "integer_array"), - coerce_optional_dispatch(t11, "double_array"), - coerce_optional_dispatch(t22, "double_array"), - coerce_optional_dispatch(t33, "double_array"), - coerce_optional_dispatch(t12, "double_array"), - coerce_optional_dispatch(t13, "double_array"), - coerce_optional_dispatch(t23, "double_array"), + check_and_coerce_optional(indp_values, DoubleArray), + check_and_coerce_optional(ent_ids, IntegerArray), + check_and_coerce_optional(t11, DoubleArray), + check_and_coerce_optional(t22, DoubleArray), + check_and_coerce_optional(t33, DoubleArray), + check_and_coerce_optional(t12, DoubleArray), + check_and_coerce_optional(t13, DoubleArray), + check_and_coerce_optional(t23, DoubleArray), ) def get_non_mesh_data( @@ -343,14 +319,11 @@ def get_non_mesh_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_non_mesh_data") check_type(ds_id, int) - if indp_values is not None: - check_type(indp_values, DoubleArray) - if non_mesh_data is not None: - check_type(non_mesh_data, DoubleArray) + return self.plot_manager.GetNonmeshData( ds_id, - coerce_optional_dispatch(indp_values, "double_array"), - coerce_optional_dispatch(non_mesh_data, "double_array"), + check_and_coerce_optional(indp_values, DoubleArray), + check_and_coerce_optional(non_mesh_data, DoubleArray), ) def get_highlight_data( @@ -369,14 +342,11 @@ def get_highlight_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_highlight_data") check_type(ds_id, int) - if indp_values is not None: - check_type(indp_values, DoubleArray) - if highlight_data is not None: - check_type(highlight_data, DoubleArray) + return self.plot_manager.GetHighlightData( ds_id, - coerce_optional_dispatch(indp_values, "double_array"), - coerce_optional_dispatch(highlight_data, "double_array"), + check_and_coerce_optional(indp_values, DoubleArray), + check_and_coerce_optional(highlight_data, DoubleArray), ) def create_user_plot(self) -> UserPlot: @@ -456,10 +426,9 @@ def get_indp_values(self, ds_id: int, values: DoubleArray | None) -> bool: """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_indp_values") check_type(ds_id, int) - if values is not None: - check_type(values, DoubleArray) + return self.plot_manager.GetIndpValues( - ds_id, coerce_optional_dispatch(values, "double_array") + ds_id, check_and_coerce_optional(values, DoubleArray) ) def get_data_nb_components(self, ds_id: int) -> int: @@ -511,10 +480,9 @@ def find_dataset_ids_by_name(self, name: str, ds_ids: IntegerArray | None) -> in """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="find_dataset_ids_by_name") check_type(name, str) - if ds_ids is not None: - check_type(ds_ids, IntegerArray) + return self.plot_manager.FindDatasetIdsByName( - name, coerce_optional_dispatch(ds_ids, "integer_array") + name, check_and_coerce_optional(ds_ids, IntegerArray) ) def create_anchor_plane( @@ -552,8 +520,7 @@ def apply_anchor_plane(self, anchor_index: int, plot: Plot | None) -> bool: """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="apply_anchor_plane") check_type(anchor_index, int) - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) return self.plot_manager.ApplyAnchorPlane( anchor_index, coerce_optional_dispatch(plot, "plot") ) @@ -748,10 +715,9 @@ def warp_query_node( process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="warp_query_node") check_type(node_id, int) check_type(anchor_index, int) - if ret_values is not None: - check_type(ret_values, DoubleArray) + return self.plot_manager.WarpQueryNode( - node_id, anchor_index, coerce_optional_dispatch(ret_values, "double_array") + node_id, anchor_index, check_and_coerce_optional(ret_values, DoubleArray) ) def warp_query_begin(self, ds_id: int, indp_values: DoubleArray | None) -> bool: @@ -767,10 +733,9 @@ def warp_query_begin(self, ds_id: int, indp_values: DoubleArray | None) -> bool: """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="warp_query_begin") check_type(ds_id, int) - if indp_values is not None: - check_type(indp_values, DoubleArray) + return self.plot_manager.WarpQueryBegin( - ds_id, coerce_optional_dispatch(indp_values, "double_array") + ds_id, check_and_coerce_optional(indp_values, DoubleArray) ) def export_to_sdz(self, file_name: str) -> bool: @@ -962,18 +927,15 @@ def fbx_export( process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="fbx_export") check_type(file_name, str) file_name = check_file_extension(file_name, FBX_FILE_EXT) - if geo_list is not None: - check_type(geo_list, EntList) - if mesh_list is not None: - check_type(mesh_list, EntList) + check_type(export_type, int) check_type(wp_scale_factor, (float, int)) check_type(sm_scale_factor, (float, int)) unit_sys = get_enum_value(unit_sys, SystemUnits) result = self.plot_manager.FBXExport( file_name, - coerce_optional_dispatch(geo_list, "ent_list"), - coerce_optional_dispatch(mesh_list, "ent_list"), + check_and_coerce_optional(geo_list, EntList), + check_and_coerce_optional(mesh_list, EntList), export_type, wp_scale_factor, sm_scale_factor, diff --git a/src/moldflow/predicate_manager.py b/src/moldflow/predicate_manager.py index 115dfef..3bf2663 100644 --- a/src/moldflow/predicate_manager.py +++ b/src/moldflow/predicate_manager.py @@ -9,7 +9,7 @@ from .predicate import Predicate from .double_array import DoubleArray from .common import CrossSectionType, LogMessage -from .helper import check_type, get_enum_value, check_range, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, get_enum_value, check_range from .com_proxy import safe_com from .logger import process_log @@ -117,13 +117,10 @@ def create_bool_and_predicate( Predicate: The created AND predicate. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_bool_and_predicate") - if predicate1 is not None: - check_type(predicate1, Predicate) - if predicate2 is not None: - check_type(predicate2, Predicate) + result = self.predicate_manager.CreateBoolAndPredicate( - coerce_optional_dispatch(predicate1, "predicate"), - coerce_optional_dispatch(predicate2, "predicate"), + check_and_coerce_optional(predicate1, Predicate), + check_and_coerce_optional(predicate2, Predicate), ) if result is None: @@ -145,13 +142,10 @@ def create_bool_or_predicate( Predicate: The created OR predicate """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_bool_or_predicate") - if predicate1 is not None: - check_type(predicate1, Predicate) - if predicate2 is not None: - check_type(predicate2, Predicate) + result = self.predicate_manager.CreateBoolOrPredicate( - coerce_optional_dispatch(predicate1, "predicate"), - coerce_optional_dispatch(predicate2, "predicate"), + check_and_coerce_optional(predicate1, Predicate), + check_and_coerce_optional(predicate2, Predicate), ) if result is None: return None @@ -169,10 +163,9 @@ def create_bool_not_predicate(self, predicate: Predicate | None) -> Predicate: Predicate: The created NOT predicate. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_bool_not_predicate") - if predicate is not None: - check_type(predicate, Predicate) + result = self.predicate_manager.CreateBoolNotPredicate( - coerce_optional_dispatch(predicate, "predicate") + check_and_coerce_optional(predicate, Predicate) ) if result is None: return None @@ -193,13 +186,10 @@ def create_bool_xor_predicate( Predicate: The created XOR predicate. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_bool_xor_predicate") - if predicate1 is not None: - check_type(predicate1, Predicate) - if predicate2 is not None: - check_type(predicate2, Predicate) + result = self.predicate_manager.CreateBoolXorPredicate( - coerce_optional_dispatch(predicate1, "predicate"), - coerce_optional_dispatch(predicate2, "predicate"), + check_and_coerce_optional(predicate1, Predicate), + check_and_coerce_optional(predicate2, Predicate), ) if result is None: @@ -241,14 +231,11 @@ def create_x_section_predicate( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_x_section_predicate") cross_section = get_enum_value(cross_section, CrossSectionType) - if min_value is not None: - check_type(min_value, DoubleArray) - if max_value is not None: - check_type(max_value, DoubleArray) + result = self.predicate_manager.CreateXSectionPredicate( cross_section, - coerce_optional_dispatch(min_value, "double_array"), - coerce_optional_dispatch(max_value, "double_array"), + check_and_coerce_optional(min_value, DoubleArray), + check_and_coerce_optional(max_value, DoubleArray), ) if result is None: diff --git a/src/moldflow/prop.py b/src/moldflow/prop.py index c4723f3..f64729a 100644 --- a/src/moldflow/prop.py +++ b/src/moldflow/prop.py @@ -9,7 +9,7 @@ from .double_array import DoubleArray from .string_array import StringArray from .logger import process_log -from .helper import check_type, check_is_non_negative, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, check_is_non_negative from .com_proxy import safe_com from .common import LogMessage @@ -209,9 +209,8 @@ def set_field_values(self, field_id: int, values: DoubleArray | None) -> None: process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_field_values") check_type(field_id, int) check_is_non_negative(field_id) - if values is not None: - check_type(values, DoubleArray) - self.prop.SetFieldValues(field_id, coerce_optional_dispatch(values, "double_array")) + + self.prop.SetFieldValues(field_id, check_and_coerce_optional(values, DoubleArray)) def field_units(self, field_id: int) -> StringArray: """ diff --git a/src/moldflow/property_editor.py b/src/moldflow/property_editor.py index 978e537..58537ac 100644 --- a/src/moldflow/property_editor.py +++ b/src/moldflow/property_editor.py @@ -9,7 +9,7 @@ from .logger import process_log, LogMessage from .ent_list import EntList from .prop import Property -from .helper import get_enum_value, check_type, coerce_optional_dispatch +from .helper import get_enum_value, check_type, check_and_coerce_optional from .com_proxy import safe_com from .common import CommitActions, MaterialDatabaseType, PropertyType @@ -116,12 +116,9 @@ def set_property(self, entities: EntList | None, prop: Property | None) -> bool: bool: True if the property was assigned successfully, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_property") - if entities is not None: - check_type(entities, EntList) - if prop is not None: - check_type(prop, Property) + return self.property_editor.SetProperty( - coerce_optional_dispatch(entities, "ent_list"), coerce_optional_dispatch(prop, "prop") + check_and_coerce_optional(entities, EntList), check_and_coerce_optional(prop, Property) ) def create_entity_list(self) -> EntList: @@ -212,9 +209,8 @@ def get_next_property(self, prop: Property | None) -> Property: Property: The next property in the list. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_property") - if prop is not None: - check_type(prop, Property) - result = self.property_editor.GetNextProperty(coerce_optional_dispatch(prop, "prop")) + + result = self.property_editor.GetNextProperty(check_and_coerce_optional(prop, Property)) if result is None: return None return Property(result) @@ -230,9 +226,10 @@ def get_next_property_of_type(self, prop: Property | None) -> Property: Property: The next property of the same type. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_property_of_type") - if prop is not None: - check_type(prop, Property) - result = self.property_editor.GetNextPropertyOfType(coerce_optional_dispatch(prop, "prop")) + + result = self.property_editor.GetNextPropertyOfType( + check_and_coerce_optional(prop, Property) + ) if result is None: return None return Property(result) @@ -248,11 +245,8 @@ def get_entity_property(self, entities: EntList | None) -> Property: Property: The property of the entities. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_entity_property") - if entities is not None: - check_type(entities, EntList) - prop = self.property_editor.GetEntityProperty( - coerce_optional_dispatch(entities, "ent_list") - ) + + prop = self.property_editor.GetEntityProperty(check_and_coerce_optional(entities, EntList)) if prop is None: return None return Property(prop) diff --git a/src/moldflow/study_doc.py b/src/moldflow/study_doc.py index 78295dd..2655172 100644 --- a/src/moldflow/study_doc.py +++ b/src/moldflow/study_doc.py @@ -11,11 +11,13 @@ from .logger import process_log from .helper import ( check_type, + check_optional_type, + coerce_optional_dispatch, + check_and_coerce_optional, check_file_extension, check_range, get_enum_value, check_is_non_negative, - coerce_optional_dispatch, ) from .com_proxy import safe_com from .common import LogMessage, MoldingProcess, MeshType @@ -154,9 +156,8 @@ def selection(self, value: EntList | None) -> None: Set selection """ process_log(__name__, LogMessage.PROPERTY_SET, locals(), name="selection", value=value) - if value is not None: - check_type(value, EntList) - self.study_doc.Selection = coerce_optional_dispatch(value, "ent_list") + + self.study_doc.Selection = check_and_coerce_optional(value, EntList) @property def number_of_analyses(self) -> int: @@ -264,8 +265,7 @@ def add_file(self, name: str, opts: ImportOptions | None, show_logs: bool) -> bo """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_file") check_type(name, str) - if opts is not None: - check_type(opts, ImportOptions) + check_optional_type(opts, ImportOptions) check_type(show_logs, bool) return self.study_doc.AddFile( name, coerce_optional_dispatch(opts, "import_options"), show_logs @@ -313,9 +313,8 @@ def get_next_node(self, node: EntList | None) -> EntList: EntList: The next node in the study """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_node") - if node is not None: - check_type(node, EntList) - result = self.study_doc.GetNextNode(coerce_optional_dispatch(node, "ent_list")) + + result = self.study_doc.GetNextNode(check_and_coerce_optional(node, EntList)) if result is None: return None return EntList(result) @@ -331,9 +330,8 @@ def get_node_coord(self, node: EntList | None) -> Vector: Vector: The coordinates of the node """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_node_coord") - if node is not None: - check_type(node, EntList) - result = self.study_doc.GetNodeCoord(coerce_optional_dispatch(node, "ent_list")) + + result = self.study_doc.GetNodeCoord(check_and_coerce_optional(node, EntList)) if result is None: return None return Vector(result) @@ -362,9 +360,8 @@ def get_next_tri(self, tri: EntList | None) -> EntList: EntList: The next triangle in the study """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_tri") - if tri is not None: - check_type(tri, EntList) - result = self.study_doc.GetNextTri(coerce_optional_dispatch(tri, "ent_list")) + + result = self.study_doc.GetNextTri(check_and_coerce_optional(tri, EntList)) if result is None: return None return EntList(result) @@ -393,9 +390,8 @@ def get_next_beam(self, beam: EntList | None) -> EntList: EntList: The next beam in the study """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_beam") - if beam is not None: - check_type(beam, EntList) - result = self.study_doc.GetNextBeam(coerce_optional_dispatch(beam, "ent_list")) + + result = self.study_doc.GetNextBeam(check_and_coerce_optional(beam, EntList)) if result is None: return None return EntList(result) @@ -424,9 +420,8 @@ def get_next_tet(self, tet: EntList | None) -> EntList: EntList: The next tetrahedral element in the study """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_tet") - if tet is not None: - check_type(tet, EntList) - result = self.study_doc.GetNextTet(coerce_optional_dispatch(tet, "ent_list")) + + result = self.study_doc.GetNextTet(check_and_coerce_optional(tet, EntList)) if result is None: return None return EntList(result) @@ -442,9 +437,8 @@ def get_elem_nodes(self, elem: EntList | None) -> EntList: EntList: The nodes of the element """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_elem_nodes") - if elem is not None: - check_type(elem, EntList) - result = self.study_doc.GetElemNodes(coerce_optional_dispatch(elem, "ent_list")) + + result = self.study_doc.GetElemNodes(check_and_coerce_optional(elem, EntList)) if result is None: return None return EntList(result) @@ -460,9 +454,8 @@ def get_entity_layer(self, ent: EntList | None) -> EntList: EntList: The layer of the entity """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_entity_layer") - if ent is not None: - check_type(ent, EntList) - result = self.study_doc.GetEntityLayer(coerce_optional_dispatch(ent, "ent_list")) + + result = self.study_doc.GetEntityLayer(check_and_coerce_optional(ent, EntList)) if result is None: return None return EntList(result) @@ -478,9 +471,8 @@ def get_entity_id(self, ent: EntList | None) -> int: int: The ID of the entity """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_entity_id") - if ent is not None: - check_type(ent, EntList) - return self.study_doc.GetEntityID(coerce_optional_dispatch(ent, "ent_list")) + + return self.study_doc.GetEntityID(check_and_coerce_optional(ent, EntList)) def get_first_curve(self) -> EntList: """ @@ -506,9 +498,8 @@ def get_next_curve(self, curve: EntList | None) -> EntList: EntList: The next curve in the study """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_curve") - if curve is not None: - check_type(curve, EntList) - result = self.study_doc.GetNextCurve(coerce_optional_dispatch(curve, "ent_list")) + + result = self.study_doc.GetNextCurve(check_and_coerce_optional(curve, EntList)) if result is None: return None return EntList(result) @@ -525,13 +516,10 @@ def get_curve_point(self, curve: EntList | None, pos_curve: float) -> Vector: Vector: The point on the curve """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_curve_point") - if curve is not None: - check_type(curve, EntList) + check_type(pos_curve, (int, float)) check_range(pos_curve, 0, 1, True, True) - result = self.study_doc.GetCurvePoint( - coerce_optional_dispatch(curve, "ent_list"), pos_curve - ) + result = self.study_doc.GetCurvePoint(check_and_coerce_optional(curve, EntList), pos_curve) if result is None: return None return Vector(result) diff --git a/src/moldflow/system_message.py b/src/moldflow/system_message.py index 96f32d2..cdcaf91 100644 --- a/src/moldflow/system_message.py +++ b/src/moldflow/system_message.py @@ -10,7 +10,7 @@ from .double_array import DoubleArray from .common import SystemUnits from .logger import process_log, LogMessage -from .helper import check_type, get_enum_value, check_is_non_negative, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, get_enum_value, check_is_non_negative from .com_proxy import safe_com @@ -50,15 +50,12 @@ def get_data_message( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_data_message") check_type(msgid, int) - if preset_text is not None: - check_type(preset_text, StringArray) - if preset_vals is not None: - check_type(preset_vals, DoubleArray) + check_is_non_negative(msgid) unit_sys = get_enum_value(unit_sys, SystemUnits) return self.system_message.GetDataMessage( msgid, - coerce_optional_dispatch(preset_text, "string_array"), - coerce_optional_dispatch(preset_vals, "double_array"), + check_and_coerce_optional(preset_text, StringArray), + check_and_coerce_optional(preset_vals, DoubleArray), unit_sys, ) diff --git a/src/moldflow/user_plot.py b/src/moldflow/user_plot.py index 15ccb3d..ad7679c 100644 --- a/src/moldflow/user_plot.py +++ b/src/moldflow/user_plot.py @@ -6,7 +6,7 @@ UserPlot Class API Wrapper """ -from .helper import check_type, get_enum_value, coerce_optional_dispatch +from .helper import check_type, check_and_coerce_optional, get_enum_value from .com_proxy import safe_com from .logger import process_log from .common import ( @@ -123,14 +123,11 @@ def add_scalar_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_scalar_data") check_type(indp_val, (int, float)) - if element_id is not None: - check_type(element_id, IntegerArray) - if data is not None: - check_type(data, DoubleArray) + return self.user_plot.AddScalarData( indp_val, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(data, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(data, DoubleArray), ) # pylint: disable=R0913, R0917 @@ -157,20 +154,13 @@ def add_vector_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_vector_data") check_type(indp_val, (int, float)) - if element_id is not None: - check_type(element_id, IntegerArray) - if vx is not None: - check_type(vx, DoubleArray) - if vy is not None: - check_type(vy, DoubleArray) - if vz is not None: - check_type(vz, DoubleArray) + return self.user_plot.AddVectorData( indp_val, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(vx, "double_array"), - coerce_optional_dispatch(vy, "double_array"), - coerce_optional_dispatch(vz, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(vx, DoubleArray), + check_and_coerce_optional(vy, DoubleArray), + check_and_coerce_optional(vz, DoubleArray), ) # pylint: disable=R0913, R0917 @@ -203,29 +193,16 @@ def add_tensor_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_tensor_data") check_type(indp_val, (int, float)) - if element_id is not None: - check_type(element_id, IntegerArray) - if t_11 is not None: - check_type(t_11, DoubleArray) - if t_22 is not None: - check_type(t_22, DoubleArray) - if t_33 is not None: - check_type(t_33, DoubleArray) - if t_12 is not None: - check_type(t_12, DoubleArray) - if t_13 is not None: - check_type(t_13, DoubleArray) - if t_23 is not None: - check_type(t_23, DoubleArray) + return self.user_plot.AddTensorData( indp_val, - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(t_11, "double_array"), - coerce_optional_dispatch(t_22, "double_array"), - coerce_optional_dispatch(t_33, "double_array"), - coerce_optional_dispatch(t_12, "double_array"), - coerce_optional_dispatch(t_13, "double_array"), - coerce_optional_dispatch(t_23, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(t_11, DoubleArray), + check_and_coerce_optional(t_22, DoubleArray), + check_and_coerce_optional(t_33, DoubleArray), + check_and_coerce_optional(t_12, DoubleArray), + check_and_coerce_optional(t_13, DoubleArray), + check_and_coerce_optional(t_23, DoubleArray), ) def build(self) -> Plot: @@ -278,13 +255,10 @@ def set_scalar_data(self, element_id: IntegerArray | None, data: DoubleArray | N bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_scalar_data") - if element_id is not None: - check_type(element_id, IntegerArray) - if data is not None: - check_type(data, DoubleArray) + return self.user_plot.SetScalarData( - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(data, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(data, DoubleArray), ) def set_vector_data( @@ -307,19 +281,12 @@ def set_vector_data( bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_vector_data") - if element_id is not None: - check_type(element_id, IntegerArray) - if vx is not None: - check_type(vx, DoubleArray) - if vy is not None: - check_type(vy, DoubleArray) - if vz is not None: - check_type(vz, DoubleArray) + return self.user_plot.SetVectorData( - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(vx, "double_array"), - coerce_optional_dispatch(vy, "double_array"), - coerce_optional_dispatch(vz, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(vx, DoubleArray), + check_and_coerce_optional(vy, DoubleArray), + check_and_coerce_optional(vz, DoubleArray), ) # pylint: disable=R0913, R0917 @@ -349,28 +316,15 @@ def set_tensor_data( bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_tensor_data") - if element_id is not None: - check_type(element_id, IntegerArray) - if t_11 is not None: - check_type(t_11, DoubleArray) - if t_22 is not None: - check_type(t_22, DoubleArray) - if t_33 is not None: - check_type(t_33, DoubleArray) - if t_12 is not None: - check_type(t_12, DoubleArray) - if t_13 is not None: - check_type(t_13, DoubleArray) - if t_23 is not None: - check_type(t_23, DoubleArray) + return self.user_plot.SetTensorData( - coerce_optional_dispatch(element_id, "integer_array"), - coerce_optional_dispatch(t_11, "double_array"), - coerce_optional_dispatch(t_22, "double_array"), - coerce_optional_dispatch(t_33, "double_array"), - coerce_optional_dispatch(t_12, "double_array"), - coerce_optional_dispatch(t_13, "double_array"), - coerce_optional_dispatch(t_23, "double_array"), + check_and_coerce_optional(element_id, IntegerArray), + check_and_coerce_optional(t_11, DoubleArray), + check_and_coerce_optional(t_22, DoubleArray), + check_and_coerce_optional(t_33, DoubleArray), + check_and_coerce_optional(t_12, DoubleArray), + check_and_coerce_optional(t_13, DoubleArray), + check_and_coerce_optional(t_23, DoubleArray), ) def add_xy_plot_data( @@ -389,14 +343,11 @@ def add_xy_plot_data( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_xy_plot_data") check_type(indp_val, (int, float)) - if x_value is not None: - check_type(x_value, DoubleArray) - if y_value is not None: - check_type(y_value, DoubleArray) + return self.user_plot.AddXYPlotData( indp_val, - coerce_optional_dispatch(x_value, "double_array"), - coerce_optional_dispatch(y_value, "double_array"), + check_and_coerce_optional(x_value, DoubleArray), + check_and_coerce_optional(y_value, DoubleArray), ) def set_xy_plot_data(self, x_value: DoubleArray | None, y_value: DoubleArray | None) -> bool: @@ -411,13 +362,10 @@ def set_xy_plot_data(self, x_value: DoubleArray | None, y_value: DoubleArray | N bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_xy_plot_data") - if x_value is not None: - check_type(x_value, DoubleArray) - if y_value is not None: - check_type(y_value, DoubleArray) + return self.user_plot.SetXYPlotData( - coerce_optional_dispatch(x_value, "double_array"), - coerce_optional_dispatch(y_value, "double_array"), + check_and_coerce_optional(x_value, DoubleArray), + check_and_coerce_optional(y_value, DoubleArray), ) def set_xy_plot_x_unit_name(self, unit_name: str) -> bool: @@ -473,9 +421,8 @@ def set_highlight_data(self, values: DoubleArray | None) -> bool: bool: True if successful, False otherwise. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_highlight_data") - if values is not None: - check_type(values, DoubleArray) - return self.user_plot.SetHighlightData(coerce_optional_dispatch(values, "double_array")) + + return self.user_plot.SetHighlightData(check_and_coerce_optional(values, DoubleArray)) def build_weldline_plot(self, plot_name: str, max_angle: float, for_overmolding: bool) -> Plot: """ diff --git a/src/moldflow/version_check.py b/src/moldflow/version_check.py index 032efda..b088e27 100644 --- a/src/moldflow/version_check.py +++ b/src/moldflow/version_check.py @@ -18,7 +18,6 @@ from importlib.metadata import version, PackageNotFoundError from typing import Tuple, Optional - # Module-level constants to avoid repeated literals and improve maintainability PACKAGE_NAME = "moldflow" NO_UPDATE_ENV_VAR = "MOLDFLOW_API_NO_UPDATE_CHECK" diff --git a/src/moldflow/viewer.py b/src/moldflow/viewer.py index 52d974a..7cd88ad 100644 --- a/src/moldflow/viewer.py +++ b/src/moldflow/viewer.py @@ -26,11 +26,13 @@ check_min_max, check_range, check_type, + check_optional_type, + coerce_optional_dispatch, + check_and_coerce_optional, get_enum_value, check_is_positive, check_is_non_negative, check_file_extension, - coerce_optional_dispatch, ) from .errors import raise_value_error from .common import ValueErrorReason @@ -76,13 +78,10 @@ def reset_view(self, normal_view: Vector | None, up_view: Vector | None) -> None up_view (Vector | None): The up view vector. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="reset_view") - if normal_view is not None: - check_type(normal_view, Vector) - if up_view is not None: - check_type(up_view, Vector) + self.viewer.ResetView( - coerce_optional_dispatch(normal_view, "vector"), - coerce_optional_dispatch(up_view, "vector"), + check_and_coerce_optional(normal_view, Vector), + check_and_coerce_optional(up_view, Vector), ) def rotate(self, angle_x: float, angle_y: float, angle_z: float) -> None: @@ -404,10 +403,8 @@ def save_image_legacy(self, filename: str, x: int | None = None, y: int | None = filename = check_file_extension( filename, (PNG_FILE_EXT, JPG_FILE_EXT, JPEG_FILE_EXT, BMP_FILE_EXT, TIF_FILE_EXT) ) - if x is not None: - check_type(x, int) - if y is not None: - check_type(y, int) + check_optional_type(x, int) + check_optional_type(y, int) # Route strictly to legacy COM methods if x is None and y is None: @@ -480,14 +477,7 @@ def add_bookmark( """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="add_bookmark") check_type(name, str) - if normal_view is not None: - check_type(normal_view, Vector) - if up_view is not None: - check_type(up_view, Vector) - if focal_point is not None: - check_type(focal_point, Vector) - if eye_position is not None: - check_type(eye_position, Vector) + check_type(clipping_range_min, (int, float)) check_is_non_negative(clipping_range_min) check_type(clipping_range_max, (int, float)) @@ -496,10 +486,10 @@ def add_bookmark( check_type(parallel_scale, (int, float)) self.viewer.AddBookmark( name, - coerce_optional_dispatch(normal_view, "vector"), - coerce_optional_dispatch(up_view, "vector"), - coerce_optional_dispatch(focal_point, "vector"), - coerce_optional_dispatch(eye_position, "vector"), + check_and_coerce_optional(normal_view, Vector), + check_and_coerce_optional(up_view, Vector), + check_and_coerce_optional(focal_point, Vector), + check_and_coerce_optional(eye_position, Vector), clipping_range_min, clipping_range_max, view_angle, @@ -514,8 +504,7 @@ def show_plot(self, plot: Plot | None) -> None: plot (Plot | None): The plot to show. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_plot") - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) self.viewer.ShowPlot(coerce_optional_dispatch(plot, "plot")) def hide_plot(self, plot: Plot | None) -> None: @@ -526,8 +515,7 @@ def hide_plot(self, plot: Plot | None) -> None: plot (Plot | None): The plot to hide. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="hide_plot") - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) self.viewer.HidePlot(coerce_optional_dispatch(plot, "plot")) def overlay_plot(self, plot: Plot | None) -> None: @@ -538,8 +526,7 @@ def overlay_plot(self, plot: Plot | None) -> None: plot (Plot | None): The plot to overlay. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="overlay_plot") - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) self.viewer.OverlayPlot(coerce_optional_dispatch(plot, "plot")) def get_plot(self, plot_id: int) -> Plot: @@ -585,9 +572,8 @@ def world_to_display(self, world_coord: Vector | None) -> Vector: Vector: The converted display coordinates. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="world_to_display") - if world_coord is not None: - check_type(world_coord, Vector) - result = self.viewer.WorldToDisplay(coerce_optional_dispatch(world_coord, "vector")) + + result = self.viewer.WorldToDisplay(check_and_coerce_optional(world_coord, Vector)) if result is None: return None return Vector(result) @@ -604,11 +590,10 @@ def create_clipping_plane(self, normal: Vector | None, distance: float) -> EntLi EntList: Object containing created clipping plane. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="create_clipping_plane") - if normal is not None: - check_type(normal, Vector) + check_type(distance, (int, float)) result = self.viewer.CreateClippingPlane( - coerce_optional_dispatch(normal, "vector"), distance + check_and_coerce_optional(normal, Vector), distance ) if result is None: return None @@ -641,14 +626,11 @@ def modify_clipping_plane( distance (float): The new distance from the origin to the clipping plane. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="modify_clipping_plane") - if plane is not None: - check_type(plane, EntList) - if normal is not None: - check_type(normal, Vector) + check_type(distance, (int, float)) self.viewer.ModifyClippingPlane( - coerce_optional_dispatch(plane, "ent_list"), - coerce_optional_dispatch(normal, "vector"), + check_and_coerce_optional(plane, EntList), + check_and_coerce_optional(normal, Vector), distance, ) @@ -667,11 +649,10 @@ def modify_clipping_plane_by_id( __name__, LogMessage.FUNCTION_CALL, locals(), name="modify_clipping_plane_by_id" ) check_type(plane_id, int) - if normal is not None: - check_type(normal, Vector) + check_type(distance, (int, float)) self.viewer.ModifyClippingPlaneByID( - plane_id, coerce_optional_dispatch(normal, "vector"), distance + plane_id, check_and_coerce_optional(normal, Vector), distance ) def delete_clipping_plane(self, plane: EntList | None) -> None: @@ -682,9 +663,8 @@ def delete_clipping_plane(self, plane: EntList | None) -> None: plane (EntList | None): The clipping plane to delete. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="delete_clipping_plane") - if plane is not None: - check_type(plane, EntList) - self.viewer.DeleteClippingPlane(coerce_optional_dispatch(plane, "ent_list")) + + self.viewer.DeleteClippingPlane(check_and_coerce_optional(plane, EntList)) def get_first_clipping_plane(self) -> EntList: """ @@ -710,9 +690,8 @@ def get_next_clipping_plane(self, plane: EntList | None) -> EntList: EntList: The next clipping plane. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="get_next_clipping_plane") - if plane is not None: - check_type(plane, EntList) - result = self.viewer.GetNextClippingPlane(coerce_optional_dispatch(plane, "ent_list")) + + result = self.viewer.GetNextClippingPlane(check_and_coerce_optional(plane, EntList)) if result is None: return None return EntList(result) @@ -726,10 +705,9 @@ def enable_clipping_plane(self, plane: EntList | None, enable: bool) -> None: enable (bool): Whether to enable or disable the clipping plane. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="enable_clipping_plane") - if plane is not None: - check_type(plane, EntList) + check_type(enable, bool) - self.viewer.EnableClippingPlane(coerce_optional_dispatch(plane, "ent_list"), enable) + self.viewer.EnableClippingPlane(check_and_coerce_optional(plane, EntList), enable) @property def active_clipping_plane(self) -> EntList: @@ -754,9 +732,8 @@ def active_clipping_plane(self, plane: EntList | None) -> None: plane: The clipping plane to set as active. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="set_active_clipping_plane") - if plane is not None: - check_type(plane, EntList) - self.viewer.SetActiveClippingPlane(coerce_optional_dispatch(plane, "ent_list")) + + self.viewer.SetActiveClippingPlane(check_and_coerce_optional(plane, EntList)) def show_plot_frame(self, plot: Plot | None, frame: int) -> None: """ @@ -767,8 +744,7 @@ def show_plot_frame(self, plot: Plot | None, frame: int) -> None: frame (int): The frame number to show. """ process_log(__name__, LogMessage.FUNCTION_CALL, locals(), name="show_plot_frame") - if plot is not None: - check_type(plot, Plot) + check_optional_type(plot, Plot) check_type(frame, int) check_is_non_negative(frame) self.viewer.ShowPlotFrame(coerce_optional_dispatch(plot, "plot"), frame) diff --git a/tests/core/test_helper.py b/tests/core/test_helper.py index a1719fa..c7dd8f1 100644 --- a/tests/core/test_helper.py +++ b/tests/core/test_helper.py @@ -18,6 +18,8 @@ check_is_negative, check_min_max, check_type, + check_optional_type, + check_and_coerce_optional, check_range, check_expected_values, get_enum_value, @@ -339,3 +341,88 @@ def test_mf_array_to_list_empty(self): assert result == [] mock_array.val.assert_not_called() + + @pytest.mark.parametrize( + "value, types", + [(None, (int, float))] + + [(None, str)] + + [(None, bool)] + + [(x, (int, float)) for x in VALID_INT + VALID_FLOAT] + + [(x, str) for x in VALID_STR] + + [(x, bool) for x in VALID_BOOL], + ) + def test_check_optional_type(self, value, types, _, caplog): + """ + Test check_optional_type function with valid values including None. + """ + check_optional_type(value, types) + assert _("Valid") in caplog.text + + @pytest.mark.parametrize( + "value, types", + [(x, (int, float)) for x in list_intersection(INVALID_FLOAT, INVALID_INT) if x is not None] + + [(x, int) for x in INVALID_INT if x is not None], + ) + def test_check_optional_type_invalid(self, value, types, _): + """ + Test check_optional_type function with invalid type (but not None). + """ + with pytest.raises(TypeError) as e: + check_optional_type(value, types) + assert _("Invalid") in str(e.value) + + @pytest.mark.parametrize("value", [None, 42, 3.14, "test"]) + def test_check_and_coerce_optional_primitives(self, value, _, caplog): + """ + Test check_and_coerce_optional with primitive types. + For primitives (int, float, str), the function should return the value as-is. + """ + if value is None: + result = check_and_coerce_optional(value, int) + # For None, should return a VARIANT null dispatch + assert result is not None # Returns a VARIANT object + elif isinstance(value, int): + result = check_and_coerce_optional(value, int) + assert result == value + assert _("Valid") in caplog.text + elif isinstance(value, float): + result = check_and_coerce_optional(value, float) + assert result == value + assert _("Valid") in caplog.text + elif isinstance(value, str): + result = check_and_coerce_optional(value, str) + assert result == value + assert _("Valid") in caplog.text + + def test_check_and_coerce_optional_com_object(self, _): + """ + Test check_and_coerce_optional with a mock COM object. + For COM objects, the function should unwrap the internal attribute. + """ + # Create a mock COM object that mimics EntList + mock_ent_list = Mock() + mock_ent_list.__class__.__name__ = 'EntList' + mock_internal = Mock() + mock_ent_list.ent_list = mock_internal + + # The function should validate the type and return the internal attribute + result = check_and_coerce_optional(mock_ent_list, type(mock_ent_list)) + assert result == mock_internal + + def test_check_and_coerce_optional_none_com_object(self, _): + """ + Test check_and_coerce_optional with None for a COM object type. + Should return a VARIANT null dispatch. + """ + mock_type = type('EntList', (), {}) + result = check_and_coerce_optional(None, mock_type) + # Should return a VARIANT object, not None + assert result is not None + + def test_check_and_coerce_optional_invalid_type(self, _): + """ + Test check_and_coerce_optional with invalid type. + """ + with pytest.raises(TypeError) as e: + check_and_coerce_optional("string", int) + assert _("Invalid") in str(e.value)