diff --git a/Makefile b/Makefile index 8c4c724f516..d4bcae3eda0 100644 --- a/Makefile +++ b/Makefile @@ -30,82 +30,82 @@ unittest: unittest-dev-241 unittest-dev-222: @echo "Running unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --fluent-version=22.2 $(PYTESTEXTRA) || poetry run python -m pytest --fluent-version=22.2 $(PYTESTRERUN) unittest-dev-231: @echo "Running unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --fluent-version=23.1 $(PYTESTEXTRA) || poetry run python -m pytest --fluent-version=23.1 $(PYTESTRERUN) unittest-dev-232: @echo "Running unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --fluent-version=23.2 $(PYTESTEXTRA) || poetry run python -m pytest --fluent-version=23.2 $(PYTESTRERUN) unittest-dev-241: @echo "Running unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --fluent-version=24.1 $(PYTESTEXTRA) || poetry run python -m pytest --fluent-version=24.1 $(PYTESTRERUN) unittest-dev-242: @echo "Running unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --fluent-version=24.2 $(PYTESTEXTRA) || poetry run python -m pytest --fluent-version=24.2 $(PYTESTRERUN) unittest-all-222: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=22.2 $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=22.2 $(PYTESTRERUN) unittest-all-222-no-codegen: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=22.2 -m "not codegen_required" $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=22.2 -m "not codegen_required" $(PYTESTRERUN) unittest-all-231: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=23.1 $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=23.1 $(PYTESTRERUN) unittest-all-231-no-codegen: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=23.1 -m "not codegen_required" $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=23.1 -m "not codegen_required" $(PYTESTRERUN) unittest-all-232: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=23.2 $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=23.2 $(PYTESTRERUN) unittest-all-232-no-codegen: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=23.2 -m "not codegen_required" $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=23.2 -m "not codegen_required" $(PYTESTRERUN) unittest-all-241: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=24.1 $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=24.1 $(PYTESTRERUN) unittest-all-241-no-codegen: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=24.1 -m "not codegen_required" $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=24.1 -m "not codegen_required" $(PYTESTRERUN) unittest-all-242: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=24.2 $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=24.2 $(PYTESTRERUN) unittest-solvermode-242: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --fluent-version=24.2 --solvermode $(PYTESTEXTRA) || poetry run python -m pytest --fluent-version=24.2 --solvermode $(PYTESTRERUN) unittest-all-242-no-codegen: @echo "Running all unittests" - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @poetry run python -m pytest --nightly --fluent-version=24.2 -m "not codegen_required" $(PYTESTEXTRA) || poetry run python -m pytest --nightly --fluent-version=24.2 -m "not codegen_required" $(PYTESTRERUN) api-codegen: @@ -122,12 +122,12 @@ build-doc-source: @sudo rm -rf doc/source/api/solver/datamodel @sudo rm -rf doc/source/api/solver/tui @sudo rm -rf doc/source/api/solver/_autosummary/settings - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @xvfb-run make -C doc html build-all-docs: @python doc/settings_rstgen.py - @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples + @sudo rm -rf /home/ansys/.local/share/ansys_fluent_core/examples/* @xvfb-run make -C doc html compare-flobject: diff --git a/src/ansys/fluent/core/data_model_cache.py b/src/ansys/fluent/core/data_model_cache.py index 2c1d58bc390..efeccc71132 100644 --- a/src/ansys/fluent/core/data_model_cache.py +++ b/src/ansys/fluent/core/data_model_cache.py @@ -102,6 +102,12 @@ def update(self, d: dict[str, Any], d1: dict[str, Any]): class DataModelCache: """Class to manage datamodel cache.""" + use_display_name = False + + def __init__(self): + self.rules_str_to_cache = defaultdict(dict) + self.rules_str_to_config = {} + class Empty: """Class representing unassigned cached state.""" @@ -121,11 +127,7 @@ def is_unassigned(state: Any) -> bool: """ return state is DataModelCache.Empty - rules_str_to_cache = defaultdict(dict) - rules_str_to_config = {} - - @staticmethod - def get_config(rules: str, name: str) -> Any: + def get_config(self, rules: str, name: str) -> Any: """Get datamodel cache configuration value. Parameters @@ -140,10 +142,9 @@ def get_config(rules: str, name: str) -> Any: Any configuration value """ - return DataModelCache.rules_str_to_config.get(rules, {}).get(name, False) + return self.rules_str_to_config.get(rules, {}).get(name, False) - @staticmethod - def set_config(rules: str, name: str, value: Any): + def set_config(self, rules: str, name: str, value: Any): """Set datamodel cache configuration value. Parameters @@ -155,13 +156,17 @@ def set_config(rules: str, name: str, value: Any): value : Any configuration value """ - if rules not in DataModelCache.rules_str_to_config: - DataModelCache.rules_str_to_config[rules] = {} - DataModelCache.rules_str_to_config[rules][name] = value + if rules not in self.rules_str_to_config: + self.rules_str_to_config[rules] = {} + self.rules_str_to_config[rules][name] = value - @staticmethod def _update_cache_from_variant_state( - rules: str, source: Dict[str, StateType], key: str, state: Variant, updaterFn + self, + rules: str, + source: Dict[str, StateType], + key: str, + state: Variant, + updaterFn, ): if state.HasField("bool_state"): updaterFn(source, key, state.bool_state) @@ -182,12 +187,12 @@ def _update_cache_from_variant_state( elif state.HasField("variant_vector_state"): updaterFn(source, key, []) for item in state.variant_vector_state.item: - DataModelCache._update_cache_from_variant_state( + self._update_cache_from_variant_state( rules, source, key, item, lambda d, k, v: d[k].append(v) ) elif state.HasField("variant_map_state"): internal_names_as_keys = ( - DataModelCache.get_config(rules, "name_key") == NameKey.INTERNAL + self.get_config(rules, "name_key") == NameKey.INTERNAL ) if ":" in key: type_, iname = key.split(":", maxsplit=1) @@ -213,14 +218,13 @@ def _update_cache_from_variant_state( source[key] = {} source = source[key] for k, v in state.variant_map_state.item.items(): - DataModelCache._update_cache_from_variant_state( + self._update_cache_from_variant_state( rules, source, k, v, dict.__setitem__ ) else: updaterFn(source, key, None) - @staticmethod - def update_cache(rules: str, state: Variant, deleted_paths: List[str]): + def update_cache(self, rules: str, state: Variant, deleted_paths: List[str]): """Update datamodel cache from streamed state. Parameters @@ -232,10 +236,8 @@ def update_cache(rules: str, state: Variant, deleted_paths: List[str]): deleted_paths : List[str] list of deleted paths """ - cache = DataModelCache.rules_str_to_cache[rules] - internal_names_as_keys = ( - DataModelCache.get_config(rules, "name_key") == NameKey.INTERNAL - ) + cache = self.rules_str_to_cache[rules] + internal_names_as_keys = self.get_config(rules, "name_key") == NameKey.INTERNAL for deleted_path in deleted_paths: comps = [x for x in deleted_path.split("/") if x] sub_cache = cache @@ -264,9 +266,7 @@ def update_cache(rules: str, state: Variant, deleted_paths: List[str]): else: break for k, v in state.variant_map_state.item.items(): - DataModelCache._update_cache_from_variant_state( - rules, cache, k, v, dict.__setitem__ - ) + self._update_cache_from_variant_state(rules, cache, k, v, dict.__setitem__) @staticmethod def _dm_path_comp(comp): @@ -276,8 +276,9 @@ def _dm_path_comp(comp): def _dm_path_comp_list(obj): return [DataModelCache._dm_path_comp(comp) for comp in obj.path] - @staticmethod - def get_state(rules: str, obj: object, name_key: Optional[NameKey] = None) -> Any: + def get_state( + self, rules: str, obj: object, name_key: Optional[NameKey] = None + ) -> Any: """Retrieve state from datamodel cache. Parameters @@ -296,10 +297,10 @@ def get_state(rules: str, obj: object, name_key: Optional[NameKey] = None) -> An state : Any cached state """ - name_key_in_config = DataModelCache.get_config(rules, "name_key") + name_key_in_config = self.get_config(rules, "name_key") if name_key == None: name_key = name_key_in_config - cache = DataModelCache.rules_str_to_cache[rules] + cache = self.rules_str_to_cache[rules] if not len(cache): return DataModelCache.Empty comps = DataModelCache._dm_path_comp_list(obj) @@ -318,8 +319,7 @@ def get_state(rules: str, obj: object, name_key: Optional[NameKey] = None) -> An return DataModelCache.Empty return _CacheImpl(name_key_in_config).transform(cache) - @staticmethod - def set_state(rules: str, obj: object, value: Any): + def set_state(self, rules: str, obj: object, value: Any): """Set datamodel cache state. Parameters @@ -331,8 +331,8 @@ def set_state(rules: str, obj: object, value: Any): value : Any state """ - name_key_in_config = DataModelCache.get_config(rules, "name_key") - cache = DataModelCache.rules_str_to_cache[rules] + name_key_in_config = self.get_config(rules, "name_key") + cache = self.rules_str_to_cache[rules] comps = DataModelCache._dm_path_comp_list(obj) for i, comp in enumerate(comps): key, next_cache = _CacheImpl(name_key_in_config).find(cache, comp, None) diff --git a/src/ansys/fluent/core/services/datamodel_se.py b/src/ansys/fluent/core/services/datamodel_se.py index 8c881c8e410..e719a5c6110 100644 --- a/src/ansys/fluent/core/services/datamodel_se.py +++ b/src/ansys/fluent/core/services/datamodel_se.py @@ -467,6 +467,7 @@ def __init__( self.event_streaming = None self.subscriptions = SubscriptionList() self.file_transfer_service = file_transfer_service + self.cache = DataModelCache() if pyfluent.DATAMODEL_USE_STATE_CACHE else None def get_attribute_value(self, rules: str, path: str, attribute: str) -> _TValue: """Get attribute value.""" @@ -856,9 +857,9 @@ def get_remote_state(self) -> Any: def get_state(self) -> Any: """Get state.""" - if pyfluent.DATAMODEL_USE_STATE_CACHE: - state = DataModelCache.get_state(self.rules, self, NameKey.DISPLAY) - if DataModelCache.is_unassigned(state): + if self.service.cache is not None: + state = self.service.cache.get_state(self.rules, self, NameKey.DISPLAY) + if self.service.cache.is_unassigned(state): state = self.get_remote_state() else: state = self.get_remote_state() diff --git a/src/ansys/fluent/core/session_pure_meshing.py b/src/ansys/fluent/core/session_pure_meshing.py index 586252b5ad5..5e3c50258c4 100644 --- a/src/ansys/fluent/core/session_pure_meshing.py +++ b/src/ansys/fluent/core/session_pure_meshing.py @@ -24,6 +24,14 @@ class PureMeshing(BaseSession): in this mode. """ + _rules = [ + "workflow", + "meshing", + "MeshingUtilities", + "PartManagement", + "PMFileManagement", + ] + def __init__( self, fluent_connection: FluentConnection, @@ -61,15 +69,26 @@ def __init__( datamodel_service_se = self._datamodel_service_se self.datamodel_streams = {} - if pyfluent.DATAMODEL_USE_STATE_CACHE: - for _rules in rules: + if datamodel_service_se.cache is not None: + for rules in PureMeshing._rules: + datamodel_service_se.cache.set_config( + rules, + "name_key", + ( + NameKey.DISPLAY + if DataModelCache.use_display_name + else NameKey.INTERNAL + ), + ) stream = DatamodelStream(datamodel_service_se) stream.register_callback( - functools.partial(DataModelCache.update_cache, rules=_rules) + functools.partial( + datamodel_service_se.cache.update_cache, rules=rules + ) ) - self.datamodel_streams[_rules] = stream + self.datamodel_streams[rules] = stream stream.start( - rules=_rules, + rules=rules, no_commands_diff_state=pyfluent.DATAMODEL_USE_NOCOMMANDS_DIFF_STATE, ) self._fluent_connection.register_finalizer_cb(stream.stop) @@ -189,15 +208,3 @@ def transfer_mesh_to_solvers( clean_up_mesh_file, overwrite_previous, ) - - -rules = [ - "workflow", - "meshing", - "MeshingUtilities", - "PartManagement", - "PMFileManagement", -] - -for r in rules: - DataModelCache.set_config(r, "name_key", NameKey.INTERNAL) diff --git a/src/ansys/fluent/core/workflow.py b/src/ansys/fluent/core/workflow.py index 52d05004c92..0c5ebe1537d 100644 --- a/src/ansys/fluent/core/workflow.py +++ b/src/ansys/fluent/core/workflow.py @@ -8,8 +8,6 @@ from typing import Any, Iterable, Iterator, List, Optional, Tuple, Union import warnings -import ansys.fluent.core as pyfluent -from ansys.fluent.core.data_model_cache import DataModelCache from ansys.fluent.core.services.datamodel_se import ( PyCallableStateObject, PyCommand, @@ -131,8 +129,10 @@ def _refresh_task_accessors(obj): def _convert_task_list_to_display_names(workflow_root, task_list): - if pyfluent.DATAMODEL_USE_STATE_CACHE: - workflow_state = DataModelCache.get_state("workflow", workflow_root) + if workflow_root.service.cache is not None: + workflow_state = workflow_root.service.cache.get_state( + "workflow", workflow_root + ) return [workflow_state[f"TaskObject:{x}"]["_name_"] for x in task_list] else: _display_names = [] diff --git a/tests/conftest.py b/tests/conftest.py index cd993cfe1ba..57d09bcb9a0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,7 +7,6 @@ from packaging.version import Version import pytest -from ansys.fluent.core.data_model_cache import DataModelCache from ansys.fluent.core.utils.fluent_version import FluentVersion _fluent_release_version = FluentVersion.current_release().value @@ -77,12 +76,6 @@ def run_before_each_test( monkeypatch.setenv("PYFLUENT_TEST_NAME", request.node.name) -@pytest.fixture(autouse=True) -def clear_datamodel_cache(): - yield - DataModelCache.rules_str_to_cache.clear() - - class Helpers: """Can be reused to provide helper methods to tests.""" diff --git a/tests/test_data_model_cache.py b/tests/test_data_model_cache.py index 983af611e90..55889ca5f49 100644 --- a/tests/test_data_model_cache.py +++ b/tests/test_data_model_cache.py @@ -5,6 +5,7 @@ ) from ansys.api.fluent.v0.variant_pb2 import Variant +import ansys.fluent.core as pyfluent from ansys.fluent.core.data_model_cache import DataModelCache, NameKey from ansys.fluent.core.services.datamodel_se import _convert_value_to_variant @@ -21,11 +22,12 @@ def __init__(self, path): def test_data_model_cache(): - DataModelCache.set_state("x", Fake([("A", ""), ("x", "")]), 42.0) - assert 42.0 == DataModelCache.get_state("x", Fake([("A", ""), ("x", "")])) - assert dict(x=42.0) == DataModelCache.get_state("x", Fake([("A", "")])) - assert DataModelCache.Empty == DataModelCache.get_state("x", Fake([("B", "")])) - assert DataModelCache.Empty == DataModelCache.get_state("y", Fake([])) + cache = DataModelCache() + cache.set_state("x", Fake([("A", ""), ("x", "")]), 42.0) + assert 42.0 == cache.get_state("x", Fake([("A", ""), ("x", "")])) + assert dict(x=42.0) == cache.get_state("x", Fake([("A", "")])) + assert DataModelCache.Empty == cache.get_state("x", Fake([("B", "")])) + assert DataModelCache.Empty == cache.get_state("y", Fake([])) @pytest.mark.parametrize( @@ -111,12 +113,13 @@ def test_data_model_cache(): def test_update_cache_display_names_as_keys( initial_cache, rules, state, deleted_paths, final_cache ): - cache_rules = DataModelCache.rules_str_to_cache + cache = DataModelCache() + cache_rules = cache.rules_str_to_cache cache_rules.clear() cache_rules.update(initial_cache) var = Variant() _convert_value_to_variant(state, var) - DataModelCache.update_cache(rules, var, deleted_paths) + cache.update_cache(rules, var, deleted_paths) assert cache_rules == final_cache @@ -201,13 +204,14 @@ def test_update_cache_display_names_as_keys( def test_update_cache_internal_names_as_keys( initial_cache, rules, state, deleted_paths, final_cache ): - DataModelCache.set_config("r1", "name_key", NameKey.INTERNAL) - cache_rules = DataModelCache.rules_str_to_cache + cache = DataModelCache() + cache.set_config("r1", "name_key", NameKey.INTERNAL) + cache_rules = cache.rules_str_to_cache cache_rules.clear() cache_rules.update(initial_cache) var = Variant() _convert_value_to_variant(state, var) - DataModelCache.update_cache(rules, var, deleted_paths) + cache.update_cache(rules, var, deleted_paths) assert cache_rules == final_cache @@ -224,31 +228,27 @@ def test_get_cached_values_in_command_arguments(new_mesh_session): @pytest.fixture def display_names_as_keys_in_cache(): - rules_list = ["workflow", "meshing", "PartManagement", "PMFileManagement"] - for rules in rules_list: - DataModelCache.set_config(rules, "name_key", NameKey.DISPLAY) + DataModelCache.use_display_name = True yield - for rules in rules_list: - DataModelCache.set_config(rules, "name_key", NameKey.INTERNAL) + DataModelCache.use_display_name = False def test_display_names_as_keys( display_names_as_keys_in_cache, new_watertight_workflow_session ): - assert "TaskObject:Import Geometry" in DataModelCache.rules_str_to_cache["workflow"] - assert "TaskObject:TaskObject1" not in DataModelCache.rules_str_to_cache["workflow"] + cache = new_watertight_workflow_session._datamodel_service_se.cache + assert "TaskObject:Import Geometry" in cache.rules_str_to_cache["workflow"] + assert "TaskObject:TaskObject1" not in cache.rules_str_to_cache["workflow"] def test_internal_names_as_keys(new_watertight_workflow_session): - assert ( - "TaskObject:Import Geometry" - not in DataModelCache.rules_str_to_cache["workflow"] - ) - assert "TaskObject:TaskObject1" in DataModelCache.rules_str_to_cache["workflow"] + cache = new_watertight_workflow_session._datamodel_service_se.cache + assert "TaskObject:Import Geometry" not in cache.rules_str_to_cache["workflow"] + assert "TaskObject:TaskObject1" in cache.rules_str_to_cache["workflow"] @pytest.mark.parametrize( - "cache,name_key_in_config,path,name_key,state", + "rules_cache,name_key_in_config,path,name_key,state", [ ({"A": {"B": {"C": 2}}}, NameKey.INTERNAL, "A/B", NameKey.INTERNAL, {"C": 2}), ( @@ -281,13 +281,14 @@ def test_internal_names_as_keys(new_watertight_workflow_session): ), ], ) -def test_cache_get_state(cache, name_key_in_config, path, name_key, state): +def test_cache_get_state(rules_cache, name_key_in_config, path, name_key, state): + cache = DataModelCache() rules = "x" - DataModelCache.set_config(rules, "name_key", name_key_in_config) - cache_rules = DataModelCache.rules_str_to_cache + cache.set_config(rules, "name_key", name_key_in_config) + cache_rules = cache.rules_str_to_cache cache_rules.clear() - cache_rules[rules] = cache - assert state == DataModelCache.get_state(rules, Fake(path), name_key) + cache_rules[rules] = rules_cache + assert state == cache.get_state(rules, Fake(path), name_key) @pytest.mark.parametrize( @@ -413,10 +414,24 @@ def test_cache_set_state( value, final_cache, ): + cache = DataModelCache() rules = "x" - DataModelCache.set_config(rules, "name_key", name_key_in_config) - cache_rules = DataModelCache.rules_str_to_cache + cache.set_config(rules, "name_key", name_key_in_config) + cache_rules = cache.rules_str_to_cache cache_rules.clear() cache_rules[rules] = initial_cache - DataModelCache.set_state(rules, Fake(path), value) + cache.set_state(rules, Fake(path), value) assert final_cache == cache_rules[rules] + + +@pytest.mark.fluent_version(">=23.2") +def test_cache_per_session(): + with ( + pyfluent.launch_fluent(mode="meshing") as m1, + pyfluent.launch_fluent(mode="meshing") as m2, + ): + assert m1.meshing.GlobalSettings.EnableComplexMeshing() + assert m2.meshing.GlobalSettings.EnableComplexMeshing() + w1 = m1.watertight() + assert not m1.meshing.GlobalSettings.EnableComplexMeshing() + assert m2.meshing.GlobalSettings.EnableComplexMeshing()