From 2b9b93d9510201869064415069c0a13761211327 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 15 Jan 2025 14:21:33 -0600 Subject: [PATCH 1/9] update cpython feature flag --- LICENSE | 42 +- .../getting_started/running_mechanical.rst | 2 +- src/ansys/mechanical/core/feature_flags.py | 103 +-- tests/test_cli.py | 849 +++++++++--------- 4 files changed, 502 insertions(+), 494 deletions(-) diff --git a/LICENSE b/LICENSE index e40f17b8d..1eaa36960 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2022 - 2025 ANSYS, Inc. and/or its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2022 - 2025 ANSYS, Inc. and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/doc/source/getting_started/running_mechanical.rst b/doc/source/getting_started/running_mechanical.rst index ac8c2773e..80ee028b7 100644 --- a/doc/source/getting_started/running_mechanical.rst +++ b/doc/source/getting_started/running_mechanical.rst @@ -83,7 +83,7 @@ usage, type the following command: with -p --features TEXT Beta feature flags to set, as a semicolon delimited list. Options: ['MultistageHarmonic', - 'ThermalShells'] + 'ThermalShells', 'CPythonCapability'] --exit Exit the application after running an input script. You can only use this command with --input-script argument (-i). The command diff --git a/src/ansys/mechanical/core/feature_flags.py b/src/ansys/mechanical/core/feature_flags.py index 813911be9..eaf9df041 100644 --- a/src/ansys/mechanical/core/feature_flags.py +++ b/src/ansys/mechanical/core/feature_flags.py @@ -1,51 +1,52 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Mechanical beta feature flags.""" - -import typing -import warnings - - -class FeatureFlags: - """Supported feature flag names.""" - - ThermalShells = "Mechanical.ThermalShells" - MultistageHarmonic = "Mechanical.MultistageHarmonic" - - -def get_feature_flag_names() -> typing.List[str]: - """Get the available feature flags.""" - return [x for x in dir(FeatureFlags) if "_" not in x] - - -def _get_flag_arg(flagname: str) -> str: - """Get the command line name for a given feature flag.""" - if hasattr(FeatureFlags, flagname): - return getattr(FeatureFlags, flagname) - warnings.warn(f"Using undocumented feature flag {flagname}") - return flagname - - -def get_command_line_arguments(flags: typing.List[str]): - """Get the command line arguments as an array for the given flags.""" - return ["-featureflags", ";".join([_get_flag_arg(flag) for flag in flags])] +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Mechanical beta feature flags.""" + +import typing +import warnings + + +class FeatureFlags: + """Supported feature flag names.""" + + ThermalShells = "Mechanical.ThermalShells" + MultistageHarmonic = "Mechanical.MultistageHarmonic" + CPythonCapability = "Mechanical.CPython.Capability" + + +def get_feature_flag_names() -> typing.List[str]: + """Get the available feature flags.""" + return [x for x in dir(FeatureFlags) if "_" not in x] + + +def _get_flag_arg(flagname: str) -> str: + """Get the command line name for a given feature flag.""" + if hasattr(FeatureFlags, flagname): + return getattr(FeatureFlags, flagname) + warnings.warn(f"Using undocumented feature flag {flagname}") + return flagname + + +def get_command_line_arguments(flags: typing.List[str]): + """Get the command line arguments as an array for the given flags.""" + return ["-featureflags", ";".join([_get_flag_arg(flag) for flag in flags])] diff --git a/tests/test_cli.py b/tests/test_cli.py index 9ce1f7000..475ff5b34 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,421 +1,428 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import os -from pathlib import Path -import subprocess -import sys - -import pytest - -from ansys.mechanical.core.ide_config import _cli_impl as ideconfig_cli_impl -from ansys.mechanical.core.ide_config import get_stubs_location, get_stubs_versions -from ansys.mechanical.core.run import _cli_impl - -STUBS_LOC = get_stubs_location() -STUBS_REVNS = get_stubs_versions(STUBS_LOC) -MIN_STUBS_REVN = min(STUBS_REVNS) -MAX_STUBS_REVN = max(STUBS_REVNS) - - -@pytest.mark.cli -def test_cli_default(disable_cli): - args, env = _cli_impl(exe="AnsysWBU.exe", version=241, port=11) - assert os.environ == env - assert "-AppModeMech" in args - assert "-b" in args - assert "-DSApplet" in args - assert "AnsysWBU.exe" in args - - -@pytest.mark.cli -def test_cli_debug(disable_cli): - _, env = _cli_impl(exe="AnsysWBU.exe", version=241, debug=True, port=11) - assert "WBDEBUG_STOP" in env - - -@pytest.mark.cli -def test_cli_graphical(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) - assert "-b" not in args - - -@pytest.mark.cli -def test_cli_appdata(disable_cli): - _, env = _cli_impl(exe="AnsysWBU.exe", version=241, private_appdata=True, port=11) - var_to_compare = "TEMP" if os.name == "nt" else "HOME" - assert os.environ[var_to_compare] != env[var_to_compare] - - -@pytest.mark.cli -def test_cli_errors(disable_cli): - # can't mix project file and input script - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=241, - project_file="foo.mechdb", - input_script="foo.py", - graphical=True, - ) - # project file only works in graphical mode - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb") - # can't mix port and project file - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb", port=11) - # can't mix port and input script - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", port=11) - - -@pytest.mark.cli -def test_cli_appmode(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, show_welcome_screen=True, graphical=True) - assert "-AppModeMech" not in args - - -@pytest.mark.cli -def test_cli_231(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=231, port=11) - assert "-nosplash" in args - assert "-notabctrl" in args - - -@pytest.mark.cli -def test_cli_port(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, port=11) - assert "-grpc" in args - assert "11" in args - - -@pytest.mark.cli -def test_cli_project(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb", graphical=True) - assert "-file" in args - assert "foo.mechdb" in args - - -@pytest.mark.cli -def test_cli_script(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", graphical=True) - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs(disable_cli): - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=241, - input_script="foo.py", - script_args="arg1,arg2,arg3", - graphical=True, - ) - assert "-ScriptArgs" in args - assert '"arg1,arg2,arg3"' in args - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs_no_script(disable_cli): - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=241, - script_args="arg1,arg2,arg3", - graphical=True, - ) - - -@pytest.mark.cli -def test_cli_scriptargs_singlequote(disable_cli): - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=241, - input_script="foo.py", - script_args="arg1,arg2,'arg3'", - graphical=True, - ) - assert "-ScriptArgs" in args - assert "\"arg1,arg2,'arg3'\"" in args - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs_doublequote(disable_cli): - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=241, - input_script="foo.py", - script_args='arg1,"arg2",arg3', - graphical=True, - ) - - -@pytest.mark.cli -def test_cli_features(disable_cli): - with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, features="a;b;c", port=11) - assert "-featureflags" in args - assert "a;b;c" in args - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, features="MultistageHarmonic", port=11) - assert "Mechanical.MultistageHarmonic" in args - - -@pytest.mark.cli -def test_cli_exit(disable_cli): - # Regardless of version, `exit` does nothing on its own - args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) - assert "-x" not in args - - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=True, port=11) - assert "-x" not in args - - # On versions earlier than 2024R1, `exit` throws a warning but does nothing - with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, input_script="foo.py") - assert "-x" not in args - - # In UI mode, exit must be manually specified - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", graphical=True) - assert "-x" not in args - - # In batch mode, exit is implied - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py") - assert "-x" in args - - # In batch mode, exit can be explicitly passed - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=True, input_script="foo.py") - assert "-x" in args - - # In batch mode, exit can not be disabled - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=False, input_script="foo.py") - assert "-x" in args - - -@pytest.mark.cli -def test_cli_batch_required_args(disable_cli): - # ansys-mechanical -r 241 => exception - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241) - - # ansys-mechanical -r 241 -g => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) - except Exception as e: - assert False, f"cli raised an exception: {e}" - - # ansys-mechanical -r 241 -i input.py => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, input_script="input.py") - except Exception as e: - assert False, f"cli raised an exception: {e}" - - # ansys-mechanical -r 241 -port 11 => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, port=11) - except Exception as e: - assert False, f"cli raised an exception: {e}" - - -def get_settings_location() -> str: - """Get the location of settings.json for user settings. - - Returns - ------- - str - The path to the settings.json file for users on Windows and Linux. - """ - if "win" in sys.platform: - settings_json = Path(os.environ.get("APPDATA")) / "Code" / "User" / "settings.json" - elif "lin" in sys.platform: - settings_json = Path(os.environ.get("HOME")) / ".config" / "Code" / "User" / "settings.json" - - return settings_json - - -@pytest.mark.cli -def test_ideconfig_cli_ide_exception(capfd, pytestconfig): - """Test IDE configuration raises an exception for anything but vscode.""" - revision = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - ideconfig_cli_impl( - ide="pycharm", - target="user", - revision=revision, - ) - - -def test_ideconfig_cli_version_exception(pytestconfig): - """Test the IDE configuration raises an exception when the version is out of bounds.""" - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - stubs_revns = get_stubs_versions(stubs_location) - - # If revision number is greater than the maximum stubs revision number - # assert an exception is raised - if revision > max(stubs_revns): - with pytest.raises(Exception): - ideconfig_cli_impl( - ide="vscode", - target="user", - revision=revision, - ) - - -@pytest.mark.cli -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_user_settings(capfd, pytestconfig): - """Test the IDE configuration prints correct information for user settings.""" - # Get the revision number - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - - # Run the IDE configuration command for the user settings type - ideconfig_cli_impl( - ide="vscode", - target="user", - revision=revision, - ) - - # Get output of the IDE configuration command - out, err = capfd.readouterr() - out = out.replace("\\\\", "\\") - - # Get the path to the settings.json file based on operating system env vars - settings_json = get_settings_location() - - assert f"Update {settings_json} with the following information" in out - assert str(stubs_location) in out - - -@pytest.mark.cli -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_workspace_settings(capfd, pytestconfig): - """Test the IDE configuration prints correct information for workplace settings.""" - # Set the revision number - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - - # Run the IDE configuration command - ideconfig_cli_impl( - ide="vscode", - target="workspace", - revision=revision, - ) - - # Get output of the IDE configuration command - out, err = capfd.readouterr() - out = out.replace("\\\\", "\\") - - # Get the path to the settings.json file based on the current directory & .vscode folder - settings_json = Path.cwd() / ".vscode" / "settings.json" - - # Assert the correct settings.json file and stubs location is in the output - assert f"Update {settings_json} with the following information" in out - assert str(stubs_location) in out - assert "Please ensure the .vscode folder is in the root of your project or repository" in out - - -@pytest.mark.cli -@pytest.mark.python_env -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_venv(test_env, run_subprocess, rootdir, pytestconfig): - """Test the IDE configuration location when a virtual environment is active.""" - # Set the revision number - revision = pytestconfig.getoption("ansys_version") - - # Install pymechanical - subprocess.check_call( - [test_env.python, "-m", "pip", "install", "-e", "."], - cwd=rootdir, - env=test_env.env, - ) - - # Get the virtual environment location - subprocess_output = run_subprocess( - [test_env.python, "-c", "'import sys; print(sys.prefix)'"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") - - # Run ansys-mechanical-ideconfig in the test virtual environment - subprocess_output_ideconfig = run_subprocess( - [ - "ansys-mechanical-ideconfig", - "--ide", - "vscode", - "--target", - "user", - "--revision", - str(revision), - ], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") - - # Assert virtual environment is in the stdout - assert venv_loc in stdout - - -@pytest.mark.cli -@pytest.mark.python_env -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_default(test_env, run_subprocess, rootdir, pytestconfig): - """Test the IDE configuration location when no arguments are supplied.""" - # Get the revision number - revision = pytestconfig.getoption("ansys_version") - # Set part of the settings.json path - settings_json_fragment = Path("Code") / "User" / "settings.json" - - # Install pymechanical - subprocess.check_call( - [test_env.python, "-m", "pip", "install", "-e", "."], - cwd=rootdir, - env=test_env.env, - ) - - # Get the virtual environment location - subprocess_output = run_subprocess( - [test_env.python, "-c", "'import sys; print(sys.prefix)'"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") - - # Run ansys-mechanical-ideconfig in the test virtual environment - subprocess_output_ideconfig = run_subprocess( - ["ansys-mechanical-ideconfig"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") - - assert revision in stdout - assert str(settings_json_fragment) in stdout - assert venv_loc in stdout +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +from pathlib import Path +import subprocess +import sys + +import pytest + +from ansys.mechanical.core.ide_config import _cli_impl as ideconfig_cli_impl +from ansys.mechanical.core.ide_config import get_stubs_location, get_stubs_versions +from ansys.mechanical.core.run import _cli_impl + +STUBS_LOC = get_stubs_location() +STUBS_REVNS = get_stubs_versions(STUBS_LOC) +MIN_STUBS_REVN = min(STUBS_REVNS) +MAX_STUBS_REVN = max(STUBS_REVNS) + + +@pytest.mark.cli +def test_cli_default(disable_cli): + args, env = _cli_impl(exe="AnsysWBU.exe", version=241, port=11) + assert os.environ == env + assert "-AppModeMech" in args + assert "-b" in args + assert "-DSApplet" in args + assert "AnsysWBU.exe" in args + + +@pytest.mark.cli +def test_cli_debug(disable_cli): + _, env = _cli_impl(exe="AnsysWBU.exe", version=241, debug=True, port=11) + assert "WBDEBUG_STOP" in env + + +@pytest.mark.cli +def test_cli_graphical(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) + assert "-b" not in args + + +@pytest.mark.cli +def test_cli_appdata(disable_cli): + _, env = _cli_impl(exe="AnsysWBU.exe", version=241, private_appdata=True, port=11) + var_to_compare = "TEMP" if os.name == "nt" else "HOME" + assert os.environ[var_to_compare] != env[var_to_compare] + + +@pytest.mark.cli +def test_cli_errors(disable_cli): + # can't mix project file and input script + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=241, + project_file="foo.mechdb", + input_script="foo.py", + graphical=True, + ) + # project file only works in graphical mode + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb") + # can't mix port and project file + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb", port=11) + # can't mix port and input script + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", port=11) + + +@pytest.mark.cli +def test_cli_appmode(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, show_welcome_screen=True, graphical=True) + assert "-AppModeMech" not in args + + +@pytest.mark.cli +def test_cli_231(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=231, port=11) + assert "-nosplash" in args + assert "-notabctrl" in args + + +@pytest.mark.cli +def test_cli_port(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, port=11) + assert "-grpc" in args + assert "11" in args + + +@pytest.mark.cli +def test_cli_project(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb", graphical=True) + assert "-file" in args + assert "foo.mechdb" in args + + +@pytest.mark.cli +def test_cli_script(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", graphical=True) + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs(disable_cli): + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=241, + input_script="foo.py", + script_args="arg1,arg2,arg3", + graphical=True, + ) + assert "-ScriptArgs" in args + assert '"arg1,arg2,arg3"' in args + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs_no_script(disable_cli): + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=241, + script_args="arg1,arg2,arg3", + graphical=True, + ) + + +@pytest.mark.cli +def test_cli_scriptargs_singlequote(disable_cli): + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=241, + input_script="foo.py", + script_args="arg1,arg2,'arg3'", + graphical=True, + ) + assert "-ScriptArgs" in args + assert "\"arg1,arg2,'arg3'\"" in args + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs_doublequote(disable_cli): + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=241, + input_script="foo.py", + script_args='arg1,"arg2",arg3', + graphical=True, + ) + + +@pytest.mark.cli +def test_cli_features(disable_cli): + with pytest.warns(UserWarning): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, features="a;b;c", port=11) + assert "-featureflags" in args + assert "a;b;c" in args + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=241, + features="ThermalShells;MultistageHarmonic;CPythonCapability", + port=11, + ) + assert "Mechanical.ThermalShells" in args + assert "Mechanical.MultistageHarmonic" in args + assert "Mechanical.CPython.Capability" in args + + +@pytest.mark.cli +def test_cli_exit(disable_cli): + # Regardless of version, `exit` does nothing on its own + args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) + assert "-x" not in args + + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=True, port=11) + assert "-x" not in args + + # On versions earlier than 2024R1, `exit` throws a warning but does nothing + with pytest.warns(UserWarning): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, input_script="foo.py") + assert "-x" not in args + + # In UI mode, exit must be manually specified + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", graphical=True) + assert "-x" not in args + + # In batch mode, exit is implied + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py") + assert "-x" in args + + # In batch mode, exit can be explicitly passed + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=True, input_script="foo.py") + assert "-x" in args + + # In batch mode, exit can not be disabled + args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=False, input_script="foo.py") + assert "-x" in args + + +@pytest.mark.cli +def test_cli_batch_required_args(disable_cli): + # ansys-mechanical -r 241 => exception + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=241) + + # ansys-mechanical -r 241 -g => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) + except Exception as e: + assert False, f"cli raised an exception: {e}" + + # ansys-mechanical -r 241 -i input.py => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, input_script="input.py") + except Exception as e: + assert False, f"cli raised an exception: {e}" + + # ansys-mechanical -r 241 -port 11 => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, port=11) + except Exception as e: + assert False, f"cli raised an exception: {e}" + + +def get_settings_location() -> str: + """Get the location of settings.json for user settings. + + Returns + ------- + str + The path to the settings.json file for users on Windows and Linux. + """ + if "win" in sys.platform: + settings_json = Path(os.environ.get("APPDATA")) / "Code" / "User" / "settings.json" + elif "lin" in sys.platform: + settings_json = Path(os.environ.get("HOME")) / ".config" / "Code" / "User" / "settings.json" + + return settings_json + + +@pytest.mark.cli +def test_ideconfig_cli_ide_exception(capfd, pytestconfig): + """Test IDE configuration raises an exception for anything but vscode.""" + revision = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + ideconfig_cli_impl( + ide="pycharm", + target="user", + revision=revision, + ) + + +def test_ideconfig_cli_version_exception(pytestconfig): + """Test the IDE configuration raises an exception when the version is out of bounds.""" + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + stubs_revns = get_stubs_versions(stubs_location) + + # If revision number is greater than the maximum stubs revision number + # assert an exception is raised + if revision > max(stubs_revns): + with pytest.raises(Exception): + ideconfig_cli_impl( + ide="vscode", + target="user", + revision=revision, + ) + + +@pytest.mark.cli +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_user_settings(capfd, pytestconfig): + """Test the IDE configuration prints correct information for user settings.""" + # Get the revision number + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + + # Run the IDE configuration command for the user settings type + ideconfig_cli_impl( + ide="vscode", + target="user", + revision=revision, + ) + + # Get output of the IDE configuration command + out, err = capfd.readouterr() + out = out.replace("\\\\", "\\") + + # Get the path to the settings.json file based on operating system env vars + settings_json = get_settings_location() + + assert f"Update {settings_json} with the following information" in out + assert str(stubs_location) in out + + +@pytest.mark.cli +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_workspace_settings(capfd, pytestconfig): + """Test the IDE configuration prints correct information for workplace settings.""" + # Set the revision number + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + + # Run the IDE configuration command + ideconfig_cli_impl( + ide="vscode", + target="workspace", + revision=revision, + ) + + # Get output of the IDE configuration command + out, err = capfd.readouterr() + out = out.replace("\\\\", "\\") + + # Get the path to the settings.json file based on the current directory & .vscode folder + settings_json = Path.cwd() / ".vscode" / "settings.json" + + # Assert the correct settings.json file and stubs location is in the output + assert f"Update {settings_json} with the following information" in out + assert str(stubs_location) in out + assert "Please ensure the .vscode folder is in the root of your project or repository" in out + + +@pytest.mark.cli +@pytest.mark.python_env +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_venv(test_env, run_subprocess, rootdir, pytestconfig): + """Test the IDE configuration location when a virtual environment is active.""" + # Set the revision number + revision = pytestconfig.getoption("ansys_version") + + # Install pymechanical + subprocess.check_call( + [test_env.python, "-m", "pip", "install", "-e", "."], + cwd=rootdir, + env=test_env.env, + ) + + # Get the virtual environment location + subprocess_output = run_subprocess( + [test_env.python, "-c", "'import sys; print(sys.prefix)'"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") + + # Run ansys-mechanical-ideconfig in the test virtual environment + subprocess_output_ideconfig = run_subprocess( + [ + "ansys-mechanical-ideconfig", + "--ide", + "vscode", + "--target", + "user", + "--revision", + str(revision), + ], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") + + # Assert virtual environment is in the stdout + assert venv_loc in stdout + + +@pytest.mark.cli +@pytest.mark.python_env +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_default(test_env, run_subprocess, rootdir, pytestconfig): + """Test the IDE configuration location when no arguments are supplied.""" + # Get the revision number + revision = pytestconfig.getoption("ansys_version") + # Set part of the settings.json path + settings_json_fragment = Path("Code") / "User" / "settings.json" + + # Install pymechanical + subprocess.check_call( + [test_env.python, "-m", "pip", "install", "-e", "."], + cwd=rootdir, + env=test_env.env, + ) + + # Get the virtual environment location + subprocess_output = run_subprocess( + [test_env.python, "-c", "'import sys; print(sys.prefix)'"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") + + # Run ansys-mechanical-ideconfig in the test virtual environment + subprocess_output_ideconfig = run_subprocess( + ["ansys-mechanical-ideconfig"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") + + assert revision in stdout + assert str(settings_json_fragment) in stdout + assert venv_loc in stdout From 5144b9ada7750139c5712b0821e2da56b8165918 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:44:03 +0000 Subject: [PATCH 2/9] chore: auto fixes from pre-commit hooks --- LICENSE | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/LICENSE b/LICENSE index 1eaa36960..e40f17b8d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2022 - 2025 ANSYS, Inc. and/or its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2022 - 2025 ANSYS, Inc. and/or its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 0a017482075ad5e1653da818b2386fa1277dc0d1 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:45:15 +0000 Subject: [PATCH 3/9] chore: adding changelog file 1049.added.md [dependabot-skip] --- doc/changelog.d/1049.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/1049.added.md diff --git a/doc/changelog.d/1049.added.md b/doc/changelog.d/1049.added.md new file mode 100644 index 000000000..521e72b9f --- /dev/null +++ b/doc/changelog.d/1049.added.md @@ -0,0 +1 @@ +Add CPython feature flag for `ansys-mechanical` cli \ No newline at end of file From f8e16e06ef98f396039c982b60d28a6eb83e492f Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Wed, 15 Jan 2025 15:42:46 -0600 Subject: [PATCH 4/9] update tests --- tests/test_cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_cli.py b/tests/test_cli.py index 475ff5b34..6fc70e753 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -187,6 +187,7 @@ def test_cli_features(disable_cli): features="ThermalShells;MultistageHarmonic;CPythonCapability", port=11, ) + args = [arg for arg in args if arg.startswith("Mechanical")][0] assert "Mechanical.ThermalShells" in args assert "Mechanical.MultistageHarmonic" in args assert "Mechanical.CPython.Capability" in args From 71cae0e6938e1762f9c0ddee8585bf45a5e0f096 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Thu, 16 Jan 2025 08:02:25 -0600 Subject: [PATCH 5/9] review changes --- src/ansys/mechanical/core/feature_flags.py | 104 ++++++++++----------- tests/test_cli.py | 97 +++++++++++-------- 2 files changed, 110 insertions(+), 91 deletions(-) diff --git a/src/ansys/mechanical/core/feature_flags.py b/src/ansys/mechanical/core/feature_flags.py index eaf9df041..bc1c7e2da 100644 --- a/src/ansys/mechanical/core/feature_flags.py +++ b/src/ansys/mechanical/core/feature_flags.py @@ -1,52 +1,52 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -"""Mechanical beta feature flags.""" - -import typing -import warnings - - -class FeatureFlags: - """Supported feature flag names.""" - - ThermalShells = "Mechanical.ThermalShells" - MultistageHarmonic = "Mechanical.MultistageHarmonic" - CPythonCapability = "Mechanical.CPython.Capability" - - -def get_feature_flag_names() -> typing.List[str]: - """Get the available feature flags.""" - return [x for x in dir(FeatureFlags) if "_" not in x] - - -def _get_flag_arg(flagname: str) -> str: - """Get the command line name for a given feature flag.""" - if hasattr(FeatureFlags, flagname): - return getattr(FeatureFlags, flagname) - warnings.warn(f"Using undocumented feature flag {flagname}") - return flagname - - -def get_command_line_arguments(flags: typing.List[str]): - """Get the command line arguments as an array for the given flags.""" - return ["-featureflags", ";".join([_get_flag_arg(flag) for flag in flags])] +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Mechanical beta feature flags.""" + +import typing +import warnings + + +class FeatureFlags: + """Supported feature flag names.""" + + ThermalShells = "Mechanical.ThermalShells" + MultistageHarmonic = "Mechanical.MultistageHarmonic" + CPython = "Mechanical.CPython.Capability" + + +def get_feature_flag_names() -> typing.List[str]: + """Get the available feature flags.""" + return [x for x in dir(FeatureFlags) if "_" not in x] + + +def _get_flag_arg(flagname: str) -> str: + """Get the command line name for a given feature flag.""" + if hasattr(FeatureFlags, flagname): + return getattr(FeatureFlags, flagname) + warnings.warn(f"Using undocumented feature flag {flagname}") + return flagname + + +def get_command_line_arguments(flags: typing.List[str]): + """Get the command line arguments as an array for the given flags.""" + return ["-featureflags", ";".join([_get_flag_arg(flag) for flag in flags])] diff --git a/tests/test_cli.py b/tests/test_cli.py index 6fc70e753..5a90d53b1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -38,8 +38,9 @@ @pytest.mark.cli -def test_cli_default(disable_cli): - args, env = _cli_impl(exe="AnsysWBU.exe", version=241, port=11) +def test_cli_default(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, env = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) assert os.environ == env assert "-AppModeMech" in args assert "-b" in args @@ -48,49 +49,56 @@ def test_cli_default(disable_cli): @pytest.mark.cli -def test_cli_debug(disable_cli): - _, env = _cli_impl(exe="AnsysWBU.exe", version=241, debug=True, port=11) +def test_cli_debug(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + _, env = _cli_impl(exe="AnsysWBU.exe", version=version, debug=True, port=11) assert "WBDEBUG_STOP" in env @pytest.mark.cli -def test_cli_graphical(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) +def test_cli_graphical(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, graphical=True) assert "-b" not in args @pytest.mark.cli -def test_cli_appdata(disable_cli): - _, env = _cli_impl(exe="AnsysWBU.exe", version=241, private_appdata=True, port=11) +def test_cli_appdata(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + _, env = _cli_impl(exe="AnsysWBU.exe", version=version, private_appdata=True, port=11) var_to_compare = "TEMP" if os.name == "nt" else "HOME" assert os.environ[var_to_compare] != env[var_to_compare] @pytest.mark.cli -def test_cli_errors(disable_cli): +def test_cli_errors(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) # can't mix project file and input script with pytest.raises(Exception): _cli_impl( exe="AnsysWBU.exe", - version=241, + version=version, project_file="foo.mechdb", input_script="foo.py", graphical=True, ) # project file only works in graphical mode with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb") + _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb") # can't mix port and project file with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb", port=11) + _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", port=11) # can't mix port and input script with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", port=11) + _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", port=11) @pytest.mark.cli -def test_cli_appmode(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, show_welcome_screen=True, graphical=True) +def test_cli_appmode(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", version=version, show_welcome_screen=True, graphical=True + ) assert "-AppModeMech" not in args @@ -102,31 +110,37 @@ def test_cli_231(disable_cli): @pytest.mark.cli -def test_cli_port(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, port=11) +def test_cli_port(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) assert "-grpc" in args assert "11" in args @pytest.mark.cli -def test_cli_project(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, project_file="foo.mechdb", graphical=True) +def test_cli_project(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", graphical=True + ) assert "-file" in args assert "foo.mechdb" in args @pytest.mark.cli -def test_cli_script(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", graphical=True) +def test_cli_script(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) assert "-script" in args assert "foo.py" in args @pytest.mark.cli -def test_cli_scriptargs(disable_cli): +def test_cli_scriptargs(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) args, _ = _cli_impl( exe="AnsysWBU.exe", - version=241, + version=version, input_script="foo.py", script_args="arg1,arg2,arg3", graphical=True, @@ -138,21 +152,23 @@ def test_cli_scriptargs(disable_cli): @pytest.mark.cli -def test_cli_scriptargs_no_script(disable_cli): +def test_cli_scriptargs_no_script(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) with pytest.raises(Exception): _cli_impl( exe="AnsysWBU.exe", - version=241, + version=version, script_args="arg1,arg2,arg3", graphical=True, ) @pytest.mark.cli -def test_cli_scriptargs_singlequote(disable_cli): +def test_cli_scriptargs_singlequote(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) args, _ = _cli_impl( exe="AnsysWBU.exe", - version=241, + version=version, input_script="foo.py", script_args="arg1,arg2,'arg3'", graphical=True, @@ -164,11 +180,12 @@ def test_cli_scriptargs_singlequote(disable_cli): @pytest.mark.cli -def test_cli_scriptargs_doublequote(disable_cli): +def test_cli_scriptargs_doublequote(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) with pytest.raises(Exception): _cli_impl( exe="AnsysWBU.exe", - version=241, + version=version, input_script="foo.py", script_args='arg1,"arg2",arg3', graphical=True, @@ -176,15 +193,16 @@ def test_cli_scriptargs_doublequote(disable_cli): @pytest.mark.cli -def test_cli_features(disable_cli): +def test_cli_features(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, features="a;b;c", port=11) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="a;b;c", port=11) assert "-featureflags" in args assert "a;b;c" in args args, _ = _cli_impl( exe="AnsysWBU.exe", - version=241, - features="ThermalShells;MultistageHarmonic;CPythonCapability", + version=version, + features="ThermalShells;MultistageHarmonic;CPython", port=11, ) args = [arg for arg in args if arg.startswith("Mechanical")][0] @@ -194,12 +212,13 @@ def test_cli_features(disable_cli): @pytest.mark.cli -def test_cli_exit(disable_cli): +def test_cli_exit(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) # Regardless of version, `exit` does nothing on its own args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) assert "-x" not in args - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=True, port=11) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, port=11) assert "-x" not in args # On versions earlier than 2024R1, `exit` throws a warning but does nothing @@ -208,19 +227,19 @@ def test_cli_exit(disable_cli): assert "-x" not in args # In UI mode, exit must be manually specified - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py", graphical=True) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) assert "-x" not in args # In batch mode, exit is implied - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, input_script="foo.py") + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py") assert "-x" in args # In batch mode, exit can be explicitly passed - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=True, input_script="foo.py") + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, input_script="foo.py") assert "-x" in args # In batch mode, exit can not be disabled - args, _ = _cli_impl(exe="AnsysWBU.exe", version=241, exit=False, input_script="foo.py") + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=False, input_script="foo.py") assert "-x" in args From a85015da9805d00d99f344568d2cf422a5765ab0 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Thu, 16 Jan 2025 08:07:28 -0600 Subject: [PATCH 6/9] renormalize file ending --- tests/test_cli.py | 896 +++++++++++++++++++++++----------------------- 1 file changed, 448 insertions(+), 448 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 5a90d53b1..f96ceeb89 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,448 +1,448 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import os -from pathlib import Path -import subprocess -import sys - -import pytest - -from ansys.mechanical.core.ide_config import _cli_impl as ideconfig_cli_impl -from ansys.mechanical.core.ide_config import get_stubs_location, get_stubs_versions -from ansys.mechanical.core.run import _cli_impl - -STUBS_LOC = get_stubs_location() -STUBS_REVNS = get_stubs_versions(STUBS_LOC) -MIN_STUBS_REVN = min(STUBS_REVNS) -MAX_STUBS_REVN = max(STUBS_REVNS) - - -@pytest.mark.cli -def test_cli_default(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, env = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) - assert os.environ == env - assert "-AppModeMech" in args - assert "-b" in args - assert "-DSApplet" in args - assert "AnsysWBU.exe" in args - - -@pytest.mark.cli -def test_cli_debug(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - _, env = _cli_impl(exe="AnsysWBU.exe", version=version, debug=True, port=11) - assert "WBDEBUG_STOP" in env - - -@pytest.mark.cli -def test_cli_graphical(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, graphical=True) - assert "-b" not in args - - -@pytest.mark.cli -def test_cli_appdata(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - _, env = _cli_impl(exe="AnsysWBU.exe", version=version, private_appdata=True, port=11) - var_to_compare = "TEMP" if os.name == "nt" else "HOME" - assert os.environ[var_to_compare] != env[var_to_compare] - - -@pytest.mark.cli -def test_cli_errors(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - # can't mix project file and input script - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=version, - project_file="foo.mechdb", - input_script="foo.py", - graphical=True, - ) - # project file only works in graphical mode - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb") - # can't mix port and project file - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", port=11) - # can't mix port and input script - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", port=11) - - -@pytest.mark.cli -def test_cli_appmode(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", version=version, show_welcome_screen=True, graphical=True - ) - assert "-AppModeMech" not in args - - -@pytest.mark.cli -def test_cli_231(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=231, port=11) - assert "-nosplash" in args - assert "-notabctrl" in args - - -@pytest.mark.cli -def test_cli_port(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) - assert "-grpc" in args - assert "11" in args - - -@pytest.mark.cli -def test_cli_project(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", graphical=True - ) - assert "-file" in args - assert "foo.mechdb" in args - - -@pytest.mark.cli -def test_cli_script(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=version, - input_script="foo.py", - script_args="arg1,arg2,arg3", - graphical=True, - ) - assert "-ScriptArgs" in args - assert '"arg1,arg2,arg3"' in args - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs_no_script(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=version, - script_args="arg1,arg2,arg3", - graphical=True, - ) - - -@pytest.mark.cli -def test_cli_scriptargs_singlequote(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=version, - input_script="foo.py", - script_args="arg1,arg2,'arg3'", - graphical=True, - ) - assert "-ScriptArgs" in args - assert "\"arg1,arg2,'arg3'\"" in args - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs_doublequote(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=version, - input_script="foo.py", - script_args='arg1,"arg2",arg3', - graphical=True, - ) - - -@pytest.mark.cli -def test_cli_features(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="a;b;c", port=11) - assert "-featureflags" in args - assert "a;b;c" in args - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=version, - features="ThermalShells;MultistageHarmonic;CPython", - port=11, - ) - args = [arg for arg in args if arg.startswith("Mechanical")][0] - assert "Mechanical.ThermalShells" in args - assert "Mechanical.MultistageHarmonic" in args - assert "Mechanical.CPython.Capability" in args - - -@pytest.mark.cli -def test_cli_exit(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - # Regardless of version, `exit` does nothing on its own - args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) - assert "-x" not in args - - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, port=11) - assert "-x" not in args - - # On versions earlier than 2024R1, `exit` throws a warning but does nothing - with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, input_script="foo.py") - assert "-x" not in args - - # In UI mode, exit must be manually specified - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) - assert "-x" not in args - - # In batch mode, exit is implied - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py") - assert "-x" in args - - # In batch mode, exit can be explicitly passed - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, input_script="foo.py") - assert "-x" in args - - # In batch mode, exit can not be disabled - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=False, input_script="foo.py") - assert "-x" in args - - -@pytest.mark.cli -def test_cli_batch_required_args(disable_cli): - # ansys-mechanical -r 241 => exception - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241) - - # ansys-mechanical -r 241 -g => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) - except Exception as e: - assert False, f"cli raised an exception: {e}" - - # ansys-mechanical -r 241 -i input.py => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, input_script="input.py") - except Exception as e: - assert False, f"cli raised an exception: {e}" - - # ansys-mechanical -r 241 -port 11 => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, port=11) - except Exception as e: - assert False, f"cli raised an exception: {e}" - - -def get_settings_location() -> str: - """Get the location of settings.json for user settings. - - Returns - ------- - str - The path to the settings.json file for users on Windows and Linux. - """ - if "win" in sys.platform: - settings_json = Path(os.environ.get("APPDATA")) / "Code" / "User" / "settings.json" - elif "lin" in sys.platform: - settings_json = Path(os.environ.get("HOME")) / ".config" / "Code" / "User" / "settings.json" - - return settings_json - - -@pytest.mark.cli -def test_ideconfig_cli_ide_exception(capfd, pytestconfig): - """Test IDE configuration raises an exception for anything but vscode.""" - revision = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - ideconfig_cli_impl( - ide="pycharm", - target="user", - revision=revision, - ) - - -def test_ideconfig_cli_version_exception(pytestconfig): - """Test the IDE configuration raises an exception when the version is out of bounds.""" - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - stubs_revns = get_stubs_versions(stubs_location) - - # If revision number is greater than the maximum stubs revision number - # assert an exception is raised - if revision > max(stubs_revns): - with pytest.raises(Exception): - ideconfig_cli_impl( - ide="vscode", - target="user", - revision=revision, - ) - - -@pytest.mark.cli -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_user_settings(capfd, pytestconfig): - """Test the IDE configuration prints correct information for user settings.""" - # Get the revision number - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - - # Run the IDE configuration command for the user settings type - ideconfig_cli_impl( - ide="vscode", - target="user", - revision=revision, - ) - - # Get output of the IDE configuration command - out, err = capfd.readouterr() - out = out.replace("\\\\", "\\") - - # Get the path to the settings.json file based on operating system env vars - settings_json = get_settings_location() - - assert f"Update {settings_json} with the following information" in out - assert str(stubs_location) in out - - -@pytest.mark.cli -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_workspace_settings(capfd, pytestconfig): - """Test the IDE configuration prints correct information for workplace settings.""" - # Set the revision number - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - - # Run the IDE configuration command - ideconfig_cli_impl( - ide="vscode", - target="workspace", - revision=revision, - ) - - # Get output of the IDE configuration command - out, err = capfd.readouterr() - out = out.replace("\\\\", "\\") - - # Get the path to the settings.json file based on the current directory & .vscode folder - settings_json = Path.cwd() / ".vscode" / "settings.json" - - # Assert the correct settings.json file and stubs location is in the output - assert f"Update {settings_json} with the following information" in out - assert str(stubs_location) in out - assert "Please ensure the .vscode folder is in the root of your project or repository" in out - - -@pytest.mark.cli -@pytest.mark.python_env -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_venv(test_env, run_subprocess, rootdir, pytestconfig): - """Test the IDE configuration location when a virtual environment is active.""" - # Set the revision number - revision = pytestconfig.getoption("ansys_version") - - # Install pymechanical - subprocess.check_call( - [test_env.python, "-m", "pip", "install", "-e", "."], - cwd=rootdir, - env=test_env.env, - ) - - # Get the virtual environment location - subprocess_output = run_subprocess( - [test_env.python, "-c", "'import sys; print(sys.prefix)'"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") - - # Run ansys-mechanical-ideconfig in the test virtual environment - subprocess_output_ideconfig = run_subprocess( - [ - "ansys-mechanical-ideconfig", - "--ide", - "vscode", - "--target", - "user", - "--revision", - str(revision), - ], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") - - # Assert virtual environment is in the stdout - assert venv_loc in stdout - - -@pytest.mark.cli -@pytest.mark.python_env -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_default(test_env, run_subprocess, rootdir, pytestconfig): - """Test the IDE configuration location when no arguments are supplied.""" - # Get the revision number - revision = pytestconfig.getoption("ansys_version") - # Set part of the settings.json path - settings_json_fragment = Path("Code") / "User" / "settings.json" - - # Install pymechanical - subprocess.check_call( - [test_env.python, "-m", "pip", "install", "-e", "."], - cwd=rootdir, - env=test_env.env, - ) - - # Get the virtual environment location - subprocess_output = run_subprocess( - [test_env.python, "-c", "'import sys; print(sys.prefix)'"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") - - # Run ansys-mechanical-ideconfig in the test virtual environment - subprocess_output_ideconfig = run_subprocess( - ["ansys-mechanical-ideconfig"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") - - assert revision in stdout - assert str(settings_json_fragment) in stdout - assert venv_loc in stdout +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +from pathlib import Path +import subprocess +import sys + +import pytest + +from ansys.mechanical.core.ide_config import _cli_impl as ideconfig_cli_impl +from ansys.mechanical.core.ide_config import get_stubs_location, get_stubs_versions +from ansys.mechanical.core.run import _cli_impl + +STUBS_LOC = get_stubs_location() +STUBS_REVNS = get_stubs_versions(STUBS_LOC) +MIN_STUBS_REVN = min(STUBS_REVNS) +MAX_STUBS_REVN = max(STUBS_REVNS) + + +@pytest.mark.cli +def test_cli_default(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, env = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) + assert os.environ == env + assert "-AppModeMech" in args + assert "-b" in args + assert "-DSApplet" in args + assert "AnsysWBU.exe" in args + + +@pytest.mark.cli +def test_cli_debug(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + _, env = _cli_impl(exe="AnsysWBU.exe", version=version, debug=True, port=11) + assert "WBDEBUG_STOP" in env + + +@pytest.mark.cli +def test_cli_graphical(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, graphical=True) + assert "-b" not in args + + +@pytest.mark.cli +def test_cli_appdata(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + _, env = _cli_impl(exe="AnsysWBU.exe", version=version, private_appdata=True, port=11) + var_to_compare = "TEMP" if os.name == "nt" else "HOME" + assert os.environ[var_to_compare] != env[var_to_compare] + + +@pytest.mark.cli +def test_cli_errors(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + # can't mix project file and input script + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=version, + project_file="foo.mechdb", + input_script="foo.py", + graphical=True, + ) + # project file only works in graphical mode + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb") + # can't mix port and project file + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", port=11) + # can't mix port and input script + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", port=11) + + +@pytest.mark.cli +def test_cli_appmode(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", version=version, show_welcome_screen=True, graphical=True + ) + assert "-AppModeMech" not in args + + +@pytest.mark.cli +def test_cli_231(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=231, port=11) + assert "-nosplash" in args + assert "-notabctrl" in args + + +@pytest.mark.cli +def test_cli_port(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) + assert "-grpc" in args + assert "11" in args + + +@pytest.mark.cli +def test_cli_project(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", graphical=True + ) + assert "-file" in args + assert "foo.mechdb" in args + + +@pytest.mark.cli +def test_cli_script(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=version, + input_script="foo.py", + script_args="arg1,arg2,arg3", + graphical=True, + ) + assert "-ScriptArgs" in args + assert '"arg1,arg2,arg3"' in args + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs_no_script(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=version, + script_args="arg1,arg2,arg3", + graphical=True, + ) + + +@pytest.mark.cli +def test_cli_scriptargs_singlequote(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=version, + input_script="foo.py", + script_args="arg1,arg2,'arg3'", + graphical=True, + ) + assert "-ScriptArgs" in args + assert "\"arg1,arg2,'arg3'\"" in args + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs_doublequote(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=version, + input_script="foo.py", + script_args='arg1,"arg2",arg3', + graphical=True, + ) + + +@pytest.mark.cli +def test_cli_features(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + with pytest.warns(UserWarning): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="a;b;c", port=11) + assert "-featureflags" in args + assert "a;b;c" in args + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=version, + features="ThermalShells;MultistageHarmonic;CPython", + port=11, + ) + args = [arg for arg in args if arg.startswith("Mechanical")][0] + assert "Mechanical.ThermalShells" in args + assert "Mechanical.MultistageHarmonic" in args + assert "Mechanical.CPython.Capability" in args + + +@pytest.mark.cli +def test_cli_exit(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + # Regardless of version, `exit` does nothing on its own + args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) + assert "-x" not in args + + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, port=11) + assert "-x" not in args + + # On versions earlier than 2024R1, `exit` throws a warning but does nothing + with pytest.warns(UserWarning): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, input_script="foo.py") + assert "-x" not in args + + # In UI mode, exit must be manually specified + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) + assert "-x" not in args + + # In batch mode, exit is implied + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py") + assert "-x" in args + + # In batch mode, exit can be explicitly passed + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, input_script="foo.py") + assert "-x" in args + + # In batch mode, exit can not be disabled + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=False, input_script="foo.py") + assert "-x" in args + + +@pytest.mark.cli +def test_cli_batch_required_args(disable_cli): + # ansys-mechanical -r 241 => exception + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=241) + + # ansys-mechanical -r 241 -g => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) + except Exception as e: + assert False, f"cli raised an exception: {e}" + + # ansys-mechanical -r 241 -i input.py => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, input_script="input.py") + except Exception as e: + assert False, f"cli raised an exception: {e}" + + # ansys-mechanical -r 241 -port 11 => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, port=11) + except Exception as e: + assert False, f"cli raised an exception: {e}" + + +def get_settings_location() -> str: + """Get the location of settings.json for user settings. + + Returns + ------- + str + The path to the settings.json file for users on Windows and Linux. + """ + if "win" in sys.platform: + settings_json = Path(os.environ.get("APPDATA")) / "Code" / "User" / "settings.json" + elif "lin" in sys.platform: + settings_json = Path(os.environ.get("HOME")) / ".config" / "Code" / "User" / "settings.json" + + return settings_json + + +@pytest.mark.cli +def test_ideconfig_cli_ide_exception(capfd, pytestconfig): + """Test IDE configuration raises an exception for anything but vscode.""" + revision = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + ideconfig_cli_impl( + ide="pycharm", + target="user", + revision=revision, + ) + + +def test_ideconfig_cli_version_exception(pytestconfig): + """Test the IDE configuration raises an exception when the version is out of bounds.""" + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + stubs_revns = get_stubs_versions(stubs_location) + + # If revision number is greater than the maximum stubs revision number + # assert an exception is raised + if revision > max(stubs_revns): + with pytest.raises(Exception): + ideconfig_cli_impl( + ide="vscode", + target="user", + revision=revision, + ) + + +@pytest.mark.cli +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_user_settings(capfd, pytestconfig): + """Test the IDE configuration prints correct information for user settings.""" + # Get the revision number + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + + # Run the IDE configuration command for the user settings type + ideconfig_cli_impl( + ide="vscode", + target="user", + revision=revision, + ) + + # Get output of the IDE configuration command + out, err = capfd.readouterr() + out = out.replace("\\\\", "\\") + + # Get the path to the settings.json file based on operating system env vars + settings_json = get_settings_location() + + assert f"Update {settings_json} with the following information" in out + assert str(stubs_location) in out + + +@pytest.mark.cli +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_workspace_settings(capfd, pytestconfig): + """Test the IDE configuration prints correct information for workplace settings.""" + # Set the revision number + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + + # Run the IDE configuration command + ideconfig_cli_impl( + ide="vscode", + target="workspace", + revision=revision, + ) + + # Get output of the IDE configuration command + out, err = capfd.readouterr() + out = out.replace("\\\\", "\\") + + # Get the path to the settings.json file based on the current directory & .vscode folder + settings_json = Path.cwd() / ".vscode" / "settings.json" + + # Assert the correct settings.json file and stubs location is in the output + assert f"Update {settings_json} with the following information" in out + assert str(stubs_location) in out + assert "Please ensure the .vscode folder is in the root of your project or repository" in out + + +@pytest.mark.cli +@pytest.mark.python_env +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_venv(test_env, run_subprocess, rootdir, pytestconfig): + """Test the IDE configuration location when a virtual environment is active.""" + # Set the revision number + revision = pytestconfig.getoption("ansys_version") + + # Install pymechanical + subprocess.check_call( + [test_env.python, "-m", "pip", "install", "-e", "."], + cwd=rootdir, + env=test_env.env, + ) + + # Get the virtual environment location + subprocess_output = run_subprocess( + [test_env.python, "-c", "'import sys; print(sys.prefix)'"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") + + # Run ansys-mechanical-ideconfig in the test virtual environment + subprocess_output_ideconfig = run_subprocess( + [ + "ansys-mechanical-ideconfig", + "--ide", + "vscode", + "--target", + "user", + "--revision", + str(revision), + ], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") + + # Assert virtual environment is in the stdout + assert venv_loc in stdout + + +@pytest.mark.cli +@pytest.mark.python_env +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_default(test_env, run_subprocess, rootdir, pytestconfig): + """Test the IDE configuration location when no arguments are supplied.""" + # Get the revision number + revision = pytestconfig.getoption("ansys_version") + # Set part of the settings.json path + settings_json_fragment = Path("Code") / "User" / "settings.json" + + # Install pymechanical + subprocess.check_call( + [test_env.python, "-m", "pip", "install", "-e", "."], + cwd=rootdir, + env=test_env.env, + ) + + # Get the virtual environment location + subprocess_output = run_subprocess( + [test_env.python, "-c", "'import sys; print(sys.prefix)'"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") + + # Run ansys-mechanical-ideconfig in the test virtual environment + subprocess_output_ideconfig = run_subprocess( + ["ansys-mechanical-ideconfig"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") + + assert revision in stdout + assert str(settings_json_fragment) in stdout + assert venv_loc in stdout From a06a4063686906c5ac0399398f0fc8a4c3e4b7c1 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Thu, 16 Jan 2025 08:23:21 -0600 Subject: [PATCH 7/9] revert file --- tests/test_cli.py | 888 +++++++++++++++++++++++----------------------- 1 file changed, 440 insertions(+), 448 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index f96ceeb89..71dd0a5f9 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,448 +1,440 @@ -# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import os -from pathlib import Path -import subprocess -import sys - -import pytest - -from ansys.mechanical.core.ide_config import _cli_impl as ideconfig_cli_impl -from ansys.mechanical.core.ide_config import get_stubs_location, get_stubs_versions -from ansys.mechanical.core.run import _cli_impl - -STUBS_LOC = get_stubs_location() -STUBS_REVNS = get_stubs_versions(STUBS_LOC) -MIN_STUBS_REVN = min(STUBS_REVNS) -MAX_STUBS_REVN = max(STUBS_REVNS) - - -@pytest.mark.cli -def test_cli_default(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, env = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) - assert os.environ == env - assert "-AppModeMech" in args - assert "-b" in args - assert "-DSApplet" in args - assert "AnsysWBU.exe" in args - - -@pytest.mark.cli -def test_cli_debug(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - _, env = _cli_impl(exe="AnsysWBU.exe", version=version, debug=True, port=11) - assert "WBDEBUG_STOP" in env - - -@pytest.mark.cli -def test_cli_graphical(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, graphical=True) - assert "-b" not in args - - -@pytest.mark.cli -def test_cli_appdata(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - _, env = _cli_impl(exe="AnsysWBU.exe", version=version, private_appdata=True, port=11) - var_to_compare = "TEMP" if os.name == "nt" else "HOME" - assert os.environ[var_to_compare] != env[var_to_compare] - - -@pytest.mark.cli -def test_cli_errors(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - # can't mix project file and input script - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=version, - project_file="foo.mechdb", - input_script="foo.py", - graphical=True, - ) - # project file only works in graphical mode - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb") - # can't mix port and project file - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", port=11) - # can't mix port and input script - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", port=11) - - -@pytest.mark.cli -def test_cli_appmode(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", version=version, show_welcome_screen=True, graphical=True - ) - assert "-AppModeMech" not in args - - -@pytest.mark.cli -def test_cli_231(disable_cli): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=231, port=11) - assert "-nosplash" in args - assert "-notabctrl" in args - - -@pytest.mark.cli -def test_cli_port(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) - assert "-grpc" in args - assert "11" in args - - -@pytest.mark.cli -def test_cli_project(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", graphical=True - ) - assert "-file" in args - assert "foo.mechdb" in args - - -@pytest.mark.cli -def test_cli_script(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=version, - input_script="foo.py", - script_args="arg1,arg2,arg3", - graphical=True, - ) - assert "-ScriptArgs" in args - assert '"arg1,arg2,arg3"' in args - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs_no_script(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=version, - script_args="arg1,arg2,arg3", - graphical=True, - ) - - -@pytest.mark.cli -def test_cli_scriptargs_singlequote(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=version, - input_script="foo.py", - script_args="arg1,arg2,'arg3'", - graphical=True, - ) - assert "-ScriptArgs" in args - assert "\"arg1,arg2,'arg3'\"" in args - assert "-script" in args - assert "foo.py" in args - - -@pytest.mark.cli -def test_cli_scriptargs_doublequote(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - _cli_impl( - exe="AnsysWBU.exe", - version=version, - input_script="foo.py", - script_args='arg1,"arg2",arg3', - graphical=True, - ) - - -@pytest.mark.cli -def test_cli_features(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="a;b;c", port=11) - assert "-featureflags" in args - assert "a;b;c" in args - args, _ = _cli_impl( - exe="AnsysWBU.exe", - version=version, - features="ThermalShells;MultistageHarmonic;CPython", - port=11, - ) - args = [arg for arg in args if arg.startswith("Mechanical")][0] - assert "Mechanical.ThermalShells" in args - assert "Mechanical.MultistageHarmonic" in args - assert "Mechanical.CPython.Capability" in args - - -@pytest.mark.cli -def test_cli_exit(disable_cli, pytestconfig): - version = int(pytestconfig.getoption("ansys_version")) - # Regardless of version, `exit` does nothing on its own - args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) - assert "-x" not in args - - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, port=11) - assert "-x" not in args - - # On versions earlier than 2024R1, `exit` throws a warning but does nothing - with pytest.warns(UserWarning): - args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, input_script="foo.py") - assert "-x" not in args - - # In UI mode, exit must be manually specified - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) - assert "-x" not in args - - # In batch mode, exit is implied - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py") - assert "-x" in args - - # In batch mode, exit can be explicitly passed - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, input_script="foo.py") - assert "-x" in args - - # In batch mode, exit can not be disabled - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=False, input_script="foo.py") - assert "-x" in args - - -@pytest.mark.cli -def test_cli_batch_required_args(disable_cli): - # ansys-mechanical -r 241 => exception - with pytest.raises(Exception): - _cli_impl(exe="AnsysWBU.exe", version=241) - - # ansys-mechanical -r 241 -g => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) - except Exception as e: - assert False, f"cli raised an exception: {e}" - - # ansys-mechanical -r 241 -i input.py => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, input_script="input.py") - except Exception as e: - assert False, f"cli raised an exception: {e}" - - # ansys-mechanical -r 241 -port 11 => no exception - try: - _cli_impl(exe="AnsysWBU.exe", version=241, port=11) - except Exception as e: - assert False, f"cli raised an exception: {e}" - - -def get_settings_location() -> str: - """Get the location of settings.json for user settings. - - Returns - ------- - str - The path to the settings.json file for users on Windows and Linux. - """ - if "win" in sys.platform: - settings_json = Path(os.environ.get("APPDATA")) / "Code" / "User" / "settings.json" - elif "lin" in sys.platform: - settings_json = Path(os.environ.get("HOME")) / ".config" / "Code" / "User" / "settings.json" - - return settings_json - - -@pytest.mark.cli -def test_ideconfig_cli_ide_exception(capfd, pytestconfig): - """Test IDE configuration raises an exception for anything but vscode.""" - revision = int(pytestconfig.getoption("ansys_version")) - with pytest.raises(Exception): - ideconfig_cli_impl( - ide="pycharm", - target="user", - revision=revision, - ) - - -def test_ideconfig_cli_version_exception(pytestconfig): - """Test the IDE configuration raises an exception when the version is out of bounds.""" - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - stubs_revns = get_stubs_versions(stubs_location) - - # If revision number is greater than the maximum stubs revision number - # assert an exception is raised - if revision > max(stubs_revns): - with pytest.raises(Exception): - ideconfig_cli_impl( - ide="vscode", - target="user", - revision=revision, - ) - - -@pytest.mark.cli -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_user_settings(capfd, pytestconfig): - """Test the IDE configuration prints correct information for user settings.""" - # Get the revision number - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - - # Run the IDE configuration command for the user settings type - ideconfig_cli_impl( - ide="vscode", - target="user", - revision=revision, - ) - - # Get output of the IDE configuration command - out, err = capfd.readouterr() - out = out.replace("\\\\", "\\") - - # Get the path to the settings.json file based on operating system env vars - settings_json = get_settings_location() - - assert f"Update {settings_json} with the following information" in out - assert str(stubs_location) in out - - -@pytest.mark.cli -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_workspace_settings(capfd, pytestconfig): - """Test the IDE configuration prints correct information for workplace settings.""" - # Set the revision number - revision = int(pytestconfig.getoption("ansys_version")) - stubs_location = get_stubs_location() - - # Run the IDE configuration command - ideconfig_cli_impl( - ide="vscode", - target="workspace", - revision=revision, - ) - - # Get output of the IDE configuration command - out, err = capfd.readouterr() - out = out.replace("\\\\", "\\") - - # Get the path to the settings.json file based on the current directory & .vscode folder - settings_json = Path.cwd() / ".vscode" / "settings.json" - - # Assert the correct settings.json file and stubs location is in the output - assert f"Update {settings_json} with the following information" in out - assert str(stubs_location) in out - assert "Please ensure the .vscode folder is in the root of your project or repository" in out - - -@pytest.mark.cli -@pytest.mark.python_env -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_venv(test_env, run_subprocess, rootdir, pytestconfig): - """Test the IDE configuration location when a virtual environment is active.""" - # Set the revision number - revision = pytestconfig.getoption("ansys_version") - - # Install pymechanical - subprocess.check_call( - [test_env.python, "-m", "pip", "install", "-e", "."], - cwd=rootdir, - env=test_env.env, - ) - - # Get the virtual environment location - subprocess_output = run_subprocess( - [test_env.python, "-c", "'import sys; print(sys.prefix)'"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") - - # Run ansys-mechanical-ideconfig in the test virtual environment - subprocess_output_ideconfig = run_subprocess( - [ - "ansys-mechanical-ideconfig", - "--ide", - "vscode", - "--target", - "user", - "--revision", - str(revision), - ], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") - - # Assert virtual environment is in the stdout - assert venv_loc in stdout - - -@pytest.mark.cli -@pytest.mark.python_env -@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) -def test_ideconfig_cli_default(test_env, run_subprocess, rootdir, pytestconfig): - """Test the IDE configuration location when no arguments are supplied.""" - # Get the revision number - revision = pytestconfig.getoption("ansys_version") - # Set part of the settings.json path - settings_json_fragment = Path("Code") / "User" / "settings.json" - - # Install pymechanical - subprocess.check_call( - [test_env.python, "-m", "pip", "install", "-e", "."], - cwd=rootdir, - env=test_env.env, - ) - - # Get the virtual environment location - subprocess_output = run_subprocess( - [test_env.python, "-c", "'import sys; print(sys.prefix)'"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") - - # Run ansys-mechanical-ideconfig in the test virtual environment - subprocess_output_ideconfig = run_subprocess( - ["ansys-mechanical-ideconfig"], - env=test_env.env, - ) - # Decode stdout and fix extra backslashes in paths - stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") - - assert revision in stdout - assert str(settings_json_fragment) in stdout - assert venv_loc in stdout +# Copyright (C) 2022 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +from pathlib import Path +import subprocess +import sys + +import pytest + +from ansys.mechanical.core.ide_config import _cli_impl as ideconfig_cli_impl +from ansys.mechanical.core.ide_config import get_stubs_location, get_stubs_versions +from ansys.mechanical.core.run import _cli_impl + +STUBS_LOC = get_stubs_location() +STUBS_REVNS = get_stubs_versions(STUBS_LOC) +MIN_STUBS_REVN = min(STUBS_REVNS) +MAX_STUBS_REVN = max(STUBS_REVNS) + + +@pytest.mark.cli +def test_cli_default(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, env = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) + assert os.environ == env + assert "-AppModeMech" in args + assert "-b" in args + assert "-DSApplet" in args + assert "AnsysWBU.exe" in args + + +@pytest.mark.cli +def test_cli_debug(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + _, env = _cli_impl(exe="AnsysWBU.exe", version=version, debug=True, port=11) + assert "WBDEBUG_STOP" in env + + +@pytest.mark.cli +def test_cli_graphical(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, graphical=True) + assert "-b" not in args + + +@pytest.mark.cli +def test_cli_appdata(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + _, env = _cli_impl(exe="AnsysWBU.exe", version=version, private_appdata=True, port=11) + var_to_compare = "TEMP" if os.name == "nt" else "HOME" + assert os.environ[var_to_compare] != env[var_to_compare] + + +@pytest.mark.cli +def test_cli_errors(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + # can't mix project file and input script + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=version, + project_file="foo.mechdb", + input_script="foo.py", + graphical=True, + ) + # project file only works in graphical mode + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb") + # can't mix port and project file + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", port=11) + # can't mix port and input script + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", port=11) + + +@pytest.mark.cli +def test_cli_appmode(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", version=version, show_welcome_screen=True, graphical=True + ) + assert "-AppModeMech" not in args + + +@pytest.mark.cli +def test_cli_231(disable_cli): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=231, port=11) + assert "-nosplash" in args + assert "-notabctrl" in args + + +@pytest.mark.cli +def test_cli_port(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, port=11) + assert "-grpc" in args + assert "11" in args + + +@pytest.mark.cli +def test_cli_project(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", version=version, project_file="foo.mechdb", graphical=True + ) + assert "-file" in args + assert "foo.mechdb" in args + + +@pytest.mark.cli +def test_cli_script(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=version, + input_script="foo.py", + script_args="arg1,arg2,arg3", + graphical=True, + ) + assert "-ScriptArgs" in args + assert '"arg1,arg2,arg3"' in args + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs_no_script(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=version, + script_args="arg1,arg2,arg3", + graphical=True, + ) + + +@pytest.mark.cli +def test_cli_scriptargs_singlequote(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=version, + input_script="foo.py", + script_args="arg1,arg2,'arg3'", + graphical=True, + ) + assert "-ScriptArgs" in args + assert "\"arg1,arg2,'arg3'\"" in args + assert "-script" in args + assert "foo.py" in args + + +@pytest.mark.cli +def test_cli_scriptargs_doublequote(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + _cli_impl( + exe="AnsysWBU.exe", + version=version, + input_script="foo.py", + script_args='arg1,"arg2",arg3', + graphical=True, + ) + + +@pytest.mark.cli +def test_cli_features(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + with pytest.warns(UserWarning): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="a;b;c", port=11) + assert "-featureflags" in args + assert "a;b;c" in args + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="MultistageHarmonic", port=11) + assert "Mechanical.MultistageHarmonic" in args + + +@pytest.mark.cli +def test_cli_exit(disable_cli, pytestconfig): + version = int(pytestconfig.getoption("ansys_version")) + # Regardless of version, `exit` does nothing on its own + args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, port=11) + assert "-x" not in args + + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, port=11) + assert "-x" not in args + + # On versions earlier than 2024R1, `exit` throws a warning but does nothing + with pytest.warns(UserWarning): + args, _ = _cli_impl(exe="AnsysWBU.exe", version=232, exit=True, input_script="foo.py") + assert "-x" not in args + + # In UI mode, exit must be manually specified + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py", graphical=True) + assert "-x" not in args + + # In batch mode, exit is implied + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, input_script="foo.py") + assert "-x" in args + + # In batch mode, exit can be explicitly passed + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=True, input_script="foo.py") + assert "-x" in args + + # In batch mode, exit can not be disabled + args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, exit=False, input_script="foo.py") + assert "-x" in args + + +@pytest.mark.cli +def test_cli_batch_required_args(disable_cli): + # ansys-mechanical -r 241 => exception + with pytest.raises(Exception): + _cli_impl(exe="AnsysWBU.exe", version=241) + + # ansys-mechanical -r 241 -g => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, graphical=True) + except Exception as e: + assert False, f"cli raised an exception: {e}" + + # ansys-mechanical -r 241 -i input.py => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, input_script="input.py") + except Exception as e: + assert False, f"cli raised an exception: {e}" + + # ansys-mechanical -r 241 -port 11 => no exception + try: + _cli_impl(exe="AnsysWBU.exe", version=241, port=11) + except Exception as e: + assert False, f"cli raised an exception: {e}" + + +def get_settings_location() -> str: + """Get the location of settings.json for user settings. + + Returns + ------- + str + The path to the settings.json file for users on Windows and Linux. + """ + if "win" in sys.platform: + settings_json = Path(os.environ.get("APPDATA")) / "Code" / "User" / "settings.json" + elif "lin" in sys.platform: + settings_json = Path(os.environ.get("HOME")) / ".config" / "Code" / "User" / "settings.json" + + return settings_json + + +@pytest.mark.cli +def test_ideconfig_cli_ide_exception(capfd, pytestconfig): + """Test IDE configuration raises an exception for anything but vscode.""" + revision = int(pytestconfig.getoption("ansys_version")) + with pytest.raises(Exception): + ideconfig_cli_impl( + ide="pycharm", + target="user", + revision=revision, + ) + + +def test_ideconfig_cli_version_exception(pytestconfig): + """Test the IDE configuration raises an exception when the version is out of bounds.""" + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + stubs_revns = get_stubs_versions(stubs_location) + + # If revision number is greater than the maximum stubs revision number + # assert an exception is raised + if revision > max(stubs_revns): + with pytest.raises(Exception): + ideconfig_cli_impl( + ide="vscode", + target="user", + revision=revision, + ) + + +@pytest.mark.cli +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_user_settings(capfd, pytestconfig): + """Test the IDE configuration prints correct information for user settings.""" + # Get the revision number + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + + # Run the IDE configuration command for the user settings type + ideconfig_cli_impl( + ide="vscode", + target="user", + revision=revision, + ) + + # Get output of the IDE configuration command + out, err = capfd.readouterr() + out = out.replace("\\\\", "\\") + + # Get the path to the settings.json file based on operating system env vars + settings_json = get_settings_location() + + assert f"Update {settings_json} with the following information" in out + assert str(stubs_location) in out + + +@pytest.mark.cli +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_workspace_settings(capfd, pytestconfig): + """Test the IDE configuration prints correct information for workplace settings.""" + # Set the revision number + revision = int(pytestconfig.getoption("ansys_version")) + stubs_location = get_stubs_location() + + # Run the IDE configuration command + ideconfig_cli_impl( + ide="vscode", + target="workspace", + revision=revision, + ) + + # Get output of the IDE configuration command + out, err = capfd.readouterr() + out = out.replace("\\\\", "\\") + + # Get the path to the settings.json file based on the current directory & .vscode folder + settings_json = Path.cwd() / ".vscode" / "settings.json" + + # Assert the correct settings.json file and stubs location is in the output + assert f"Update {settings_json} with the following information" in out + assert str(stubs_location) in out + assert "Please ensure the .vscode folder is in the root of your project or repository" in out + + +@pytest.mark.cli +@pytest.mark.python_env +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_venv(test_env, run_subprocess, rootdir, pytestconfig): + """Test the IDE configuration location when a virtual environment is active.""" + # Set the revision number + revision = pytestconfig.getoption("ansys_version") + + # Install pymechanical + subprocess.check_call( + [test_env.python, "-m", "pip", "install", "-e", "."], + cwd=rootdir, + env=test_env.env, + ) + + # Get the virtual environment location + subprocess_output = run_subprocess( + [test_env.python, "-c", "'import sys; print(sys.prefix)'"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") + + # Run ansys-mechanical-ideconfig in the test virtual environment + subprocess_output_ideconfig = run_subprocess( + [ + "ansys-mechanical-ideconfig", + "--ide", + "vscode", + "--target", + "user", + "--revision", + str(revision), + ], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") + + # Assert virtual environment is in the stdout + assert venv_loc in stdout + + +@pytest.mark.cli +@pytest.mark.python_env +@pytest.mark.version_range(MIN_STUBS_REVN, MAX_STUBS_REVN) +def test_ideconfig_cli_default(test_env, run_subprocess, rootdir, pytestconfig): + """Test the IDE configuration location when no arguments are supplied.""" + # Get the revision number + revision = pytestconfig.getoption("ansys_version") + # Set part of the settings.json path + settings_json_fragment = Path("Code") / "User" / "settings.json" + + # Install pymechanical + subprocess.check_call( + [test_env.python, "-m", "pip", "install", "-e", "."], + cwd=rootdir, + env=test_env.env, + ) + + # Get the virtual environment location + subprocess_output = run_subprocess( + [test_env.python, "-c", "'import sys; print(sys.prefix)'"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + venv_loc = subprocess_output[1].decode().replace("\\\\", "\\") + + # Run ansys-mechanical-ideconfig in the test virtual environment + subprocess_output_ideconfig = run_subprocess( + ["ansys-mechanical-ideconfig"], + env=test_env.env, + ) + # Decode stdout and fix extra backslashes in paths + stdout = subprocess_output_ideconfig[1].decode().replace("\\\\", "\\") + + assert revision in stdout + assert str(settings_json_fragment) in stdout + assert venv_loc in stdout From 2ab1429bd0c3f6c615233c85da6d43dd63060f5c Mon Sep 17 00:00:00 2001 From: Dipin <26918585+dipinknair@users.noreply.github.com> Date: Thu, 16 Jan 2025 08:30:49 -0600 Subject: [PATCH 8/9] Update doc/source/getting_started/running_mechanical.rst --- doc/source/getting_started/running_mechanical.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/getting_started/running_mechanical.rst b/doc/source/getting_started/running_mechanical.rst index 5d4f786eb..f9c4d2ad0 100644 --- a/doc/source/getting_started/running_mechanical.rst +++ b/doc/source/getting_started/running_mechanical.rst @@ -83,7 +83,7 @@ usage, type the following command: with -p --features TEXT Beta feature flags to set, as a semicolon delimited list. Options: ['MultistageHarmonic', - 'ThermalShells', 'CPythonCapability'] + 'ThermalShells', 'CPython'] --exit Exit the application after running an input script. You can only use this command with --input-script argument (-i). The command From 1ff237735926010d1b51f4e8a60aa77e64171da6 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Thu, 16 Jan 2025 08:33:29 -0600 Subject: [PATCH 9/9] test update --- tests/test_cli.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 71dd0a5f9..5a90d53b1 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -199,8 +199,16 @@ def test_cli_features(disable_cli, pytestconfig): args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="a;b;c", port=11) assert "-featureflags" in args assert "a;b;c" in args - args, _ = _cli_impl(exe="AnsysWBU.exe", version=version, features="MultistageHarmonic", port=11) + args, _ = _cli_impl( + exe="AnsysWBU.exe", + version=version, + features="ThermalShells;MultistageHarmonic;CPython", + port=11, + ) + args = [arg for arg in args if arg.startswith("Mechanical")][0] + assert "Mechanical.ThermalShells" in args assert "Mechanical.MultistageHarmonic" in args + assert "Mechanical.CPython.Capability" in args @pytest.mark.cli