Skip to content

Commit 076d9dc

Browse files
Samuelopez-ansysMaxJPReyPipKat
authored
FIX: Create virtual environment per Python version (#4681)
Co-authored-by: Maxime Rey <[email protected]> Co-authored-by: Kathy Pippert <[email protected]>
1 parent f55f1ed commit 076d9dc

32 files changed

+935
-667
lines changed

_unittest/test_01_toolkit_icons.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,5 @@ def validate_file_exists_and_pyaedt_tabs_added(file_path):
110110
root = tree.getroot()
111111
panels = root.findall("./panel")
112112
panel_names = [panel.attrib["label"] for panel in panels]
113-
assert "Panel_PyAEDT_Toolkits" in panel_names
113+
assert "Panel_PyAEDT_Extensions" in panel_names
114114
return root

doc/source/Getting_started/Installation.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ using the CPython interpreter included in the AEDT installation.
1919

2020
In order to do that you can:
2121

22-
- Download the following file: :download:`PyAEDT Installer Python file <../Resources/PyAEDTInstallerFromDesktop.py>`
22+
- Download the following file: :download:`PyAEDT Installer Python file <../Resources/pyaedt_installer_from_aedt.py>`
2323

2424
- Open an Electronics Desktop Session and click on Tools->Run Script and execute the file.
2525

@@ -44,16 +44,16 @@ Starting from 2023R2, buttons are available in the Automation Tab as in the exam
4444
:alt: PyAEDT toolkit buttons available in AEDT
4545

4646

47-
Toolkit Manager
48-
~~~~~~~~~~~~~~~
49-
The user can install or uninstall automated workflows using the toolkit manager.
47+
Extension manager
48+
~~~~~~~~~~~~~~~~~
49+
The user can install or uninstall automated workflows using the extension manager.
5050
There are three options:
5151

5252
- Custom PyAEDT scripts.
5353

54-
- Internal PyAEDT scripts. Existing workflows in the PyAEDT library.
54+
- Existing workflows in the PyAEDT library.
5555

56-
- Open source PyAEDT toolkits. Open source PyAEDT toolkits following the `common library <https://aedt.common.toolkit.docs.pyansys.com/>`_ standard.
56+
- Open source PyAEDT toolkits described in the `PyAEDT Common Toolkit documentation <https://aedt.common.toolkit.docs.pyansys.com/>`_.
5757

5858
.. image:: ../Resources/toolkit_manager_1.png
5959
:width: 800

doc/source/Getting_started/Troubleshooting.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ run the Python command:
5050
5151
5252
Another option to install PyAEDT from the wheelhouse is to download the following file
53-
:download:`PyAEDT Installer Python file <../Resources/PyAEDTInstallerFromDesktop.py>`.
53+
:download:`PyAEDT Installer Python file <../Resources/pyaedt_installer_from_aedt.py>`.
5454
Run this script directly from AEDT and pass the wheelhouse file name as an argument.
5555

5656

doc/source/Resources/PyAEDTInstallerFromDesktop.py renamed to doc/source/Resources/pyaedt_installer_from_aedt.py

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,28 @@
88
is_linux = os.name == "posix"
99
is_windows = not is_linux
1010

11+
VENV_DIR_PREFIX = ".pyaedt_env"
12+
1113

1214
def run_pyinstaller_from_c_python(oDesktop):
13-
# This is called when run from IronPython
15+
# Iron Python script to create the virtual environment and install PyAEDT
16+
# Get AEDT information
1417
version = oDesktop.GetVersion()[2:6].replace(".", "")
15-
python_version = "3.10"
16-
if version <= "231":
17-
python_version = "3.7"
18+
# From AEDT 2023.2 the installed CPython version is 3.10
19+
python_version = "3.10" if version > "231" else "3.7"
20+
python_version_new = python_version.replace(".", "_")
21+
# AEDT installation root
1822
edt_root = os.path.normpath(oDesktop.GetExeDir())
23+
# CPython interpreter executable
1924
if is_windows:
20-
python_exe = os.path.normpath(os.path.join(edt_root, "commonfiles", "CPython", python_version.replace(".", "_"),
25+
python_exe = os.path.normpath(os.path.join(edt_root, "commonfiles", "CPython", python_version_new,
2126
"winx64", "Release", "python", "python.exe"))
2227
else:
23-
python_exe = os.path.normpath(os.path.join(edt_root, "commonfiles", "CPython", python_version.replace(".", "_"),
28+
python_exe = os.path.normpath(os.path.join(edt_root, "commonfiles", "CPython", python_version_new,
2429
"linx64", "Release", "python", "runpython"))
30+
31+
# Launch this script again from the CPython interpreter. This calls the ``install_pyaedt()`` method,
32+
# which creates a virtual environment and installs PyAEDT and its dependencies
2533
command = ['"{}"'.format(python_exe), '"{}"'.format(os.path.normpath(__file__)), "--version=" + version]
2634
if is_student_version(oDesktop):
2735
command.append("--student")
@@ -42,17 +50,21 @@ def run_pyinstaller_from_c_python(oDesktop):
4250
return_code = run_command(" ".join(command))
4351
err_msg = "There was an error while installing PyAEDT. Refer to the Terminal window where AEDT was launched " \
4452
"from."
45-
if is_windows:
46-
venv_dir = os.path.join(os.environ["APPDATA"], "pyaedt_env_ide", "v" + version)
47-
python_exe = os.path.join(venv_dir, "Scripts", "python.exe")
48-
else:
49-
venv_dir = os.path.join(os.environ["HOME"], "pyaedt_env_ide", "v" + version)
50-
python_exe = os.path.join(venv_dir, "bin", "python")
53+
5154
if str(return_code) != "0":
5255
oDesktop.AddMessage("", "", 2, err_msg)
5356
return
5457
else:
5558
oDesktop.AddMessage("", "", 0, "PyAEDT virtual environment created.")
59+
60+
# Add PyAEDT tabs in AEDT
61+
# Virtual environment path and Python executable
62+
if is_windows:
63+
venv_dir = os.path.join(os.environ["APPDATA"], VENV_DIR_PREFIX, python_version_new)
64+
python_exe = os.path.join(venv_dir, "Scripts", "python.exe")
65+
else:
66+
venv_dir = os.path.join(os.environ["HOME"], VENV_DIR_PREFIX, python_version_new)
67+
python_exe = os.path.join(venv_dir, "bin", "python")
5668
pyaedt_path = os.path.join(venv_dir, "Lib", "site-packages", "pyaedt")
5769
if is_linux:
5870
for dirpath, dirnames, _ in os.walk(venv_dir):
@@ -62,35 +74,51 @@ def run_pyinstaller_from_c_python(oDesktop):
6274
)
6375
if os.path.isdir(pyaedt_path):
6476
break
77+
78+
# Create PyAEDT symbolic link in PersonalLib
6579
personal_lib_dir = oDesktop.GetPersonalLibDirectory()
6680
pers1 = os.path.join(personal_lib_dir, "pyaedt")
81+
6782
if os.path.exists(pers1):
68-
oDesktop.AddMessage("", "", 2, "PersonalLib already mapped.")
69-
else:
7083
if is_windows:
71-
command = 'mklink /D "{}" "{}"'.format(pers1, pyaedt_path)
84+
command = 'rmdir "{}"'.format(pers1)
7285
else:
73-
command = 'ln -s "{}" "{}"'.format(pyaedt_path, pers1)
86+
command = 'rm "{}"'.format(pers1)
7487
ret_code = os.system(command)
7588
if ret_code != 0:
76-
oDesktop.AddMessage("", "", 2, "Error configuring symbolic link to pyaedt in PersonalLib.")
89+
oDesktop.AddMessage("", "", 2,
90+
"Error occurred while removing the symbolic link to PyAEDT in 'PersonalLib'.")
91+
92+
if is_windows:
93+
command = 'mklink /D "{}" "{}"'.format(pers1, pyaedt_path)
94+
else:
95+
command = 'ln -s "{}" "{}"'.format(pyaedt_path, pers1)
96+
ret_code = os.system(command)
97+
if ret_code != 0:
98+
oDesktop.AddMessage("", "", 2, "Error occurred while configuring the symbolic link to PyAEDT in 'PersonalLib'.")
99+
100+
# Create Toolkits in PersonalLib
77101
import tempfile
78102
python_script = os.path.join(tempfile.gettempdir(), "configure_pyaedt.py")
103+
if os.path.isfile(python_script):
104+
os.remove(python_script)
79105
with open(python_script, "w") as f:
80106
# enable in debu mode
81107
# f.write("import sys\n")
82108
# f.write('sys.path.insert(0, r"c:\\ansysdev\\git\\repos\\pyaedt")\n')
83109
f.write("from pyaedt.workflows.installer.pyaedt_installer import add_pyaedt_to_aedt\n")
84110
f.write(
85-
'add_pyaedt_to_aedt(aedt_version="{}", personallib=r"{}")\n'.format(
111+
'add_pyaedt_to_aedt(aedt_version="{}", personal_lib=r"{}")\n'.format(
86112
oDesktop.GetVersion()[:6], oDesktop.GetPersonalLibDirectory()))
87113

88114
command = r'"{}" "{}"'.format(python_exe, python_script)
89-
oDesktop.AddMessage("", "", 0, "Configuring PyAEDT Tabs.")
115+
oDesktop.AddMessage("", "", 0, "Configuring PyAEDT panels in automation tab.")
90116
ret_code = os.system(command)
91117
if ret_code != 0:
92-
oDesktop.AddMessage("", "", 2, "Error configuring the configuration Tab.")
118+
oDesktop.AddMessage("", "", 2, "Error occurred configuring the PyAEDT panels.")
93119
return
120+
# Refresh UI
121+
oDesktop.CloseAllWindows()
94122
if version >= "232":
95123
oDesktop.RefreshToolkitUI()
96124
msg = "PyAEDT configuration complete."
@@ -102,6 +130,7 @@ def run_pyinstaller_from_c_python(oDesktop):
102130
from System.Windows.Forms import MessageBox, MessageBoxButtons, MessageBoxIcon
103131
oDesktop.AddMessage("", "", 0, msg)
104132
MessageBox.Show(msg, 'Info', MessageBoxButtons.OK, MessageBoxIcon.Information)
133+
oDesktop.AddMessage("", "", 0, "Create a project if the PyAEDT panel is not visible.")
105134

106135

107136
def parse_arguments_for_pyaedt_installer(args=None):
@@ -123,12 +152,17 @@ def parse_arguments_for_pyaedt_installer(args=None):
123152
def install_pyaedt():
124153
# This is called when run from CPython
125154
args = parse_arguments_for_pyaedt_installer()
155+
156+
python_version = "3_10"
157+
if args.version <= "231":
158+
python_version = "3_7"
159+
126160
if is_windows:
127-
venv_dir = os.path.join(os.environ["APPDATA"], "pyaedt_env_ide", "v" + args.version)
161+
venv_dir = os.path.join(os.environ["APPDATA"], VENV_DIR_PREFIX, python_version)
128162
python_exe = os.path.join(venv_dir, "Scripts", "python.exe")
129163
pip_exe = os.path.join(venv_dir, "Scripts", "pip.exe")
130164
else:
131-
venv_dir = os.path.join(os.environ["HOME"], "pyaedt_env_ide", "v" + args.version)
165+
venv_dir = os.path.join(os.environ["HOME"], VENV_DIR_PREFIX, python_version)
132166
python_exe = os.path.join(venv_dir, "bin", "python")
133167
pip_exe = os.path.join(venv_dir, "bin", "pip")
134168
os.environ["ANSYSEM_ROOT{}".format(args.version)] = args.edt_root
@@ -158,14 +192,14 @@ def install_pyaedt():
158192
run_command('"{}" -m venv "{}"'.format(sys.executable, venv_dir))
159193

160194
if args.wheel and os.path.exists(args.wheel):
161-
wheelpyaedt = args.wheel
195+
wheel_pyaedt = args.wheel
162196
import zipfile
163-
unzipped_path = os.path.join(os.path.dirname(wheelpyaedt),
164-
os.path.splitext(os.path.basename(wheelpyaedt))[0])
197+
unzipped_path = os.path.join(os.path.dirname(wheel_pyaedt),
198+
os.path.splitext(os.path.basename(wheel_pyaedt))[0])
165199
if os.path.exists(unzipped_path):
166200
shutil.rmtree(unzipped_path, ignore_errors=True)
167-
with zipfile.ZipFile(wheelpyaedt, 'r') as zip_ref:
168-
# Extract all contents to a directory (you can specify a different extraction path if needed)
201+
with zipfile.ZipFile(wheel_pyaedt, 'r') as zip_ref:
202+
# Extract all contents to a directory. (You can specify a different extraction path if needed.)
169203
zip_ref.extractall(unzipped_path)
170204

171205
run_command(
@@ -178,7 +212,7 @@ def install_pyaedt():
178212
run_command('"{}" -m pip install --upgrade pip'.format(python_exe))
179213
run_command('"{}" --default-timeout=1000 install wheel'.format(pip_exe))
180214
# run_command(
181-
# '"{}" --default-timeout=1000 install git+https://github.com/ansys/pyaedt.git@fix/main'.format(pip_exe))
215+
# '"{}" --default-timeout=1000 install git+https://github.com/ansys/pyaedt.git@main'.format(pip_exe))
182216
run_command('"{}" --default-timeout=1000 install pyaedt[all]'.format(pip_exe))
183217
run_command('"{}" --default-timeout=1000 install jupyterlab'.format(pip_exe))
184218
run_command('"{}" --default-timeout=1000 install ipython -U'.format(pip_exe))
@@ -191,14 +225,14 @@ def install_pyaedt():
191225
run_command('"{}" uninstall --yes pyaedt'.format(pip_exe))
192226

193227
if args.wheel and os.path.exists(args.wheel):
194-
wheelpyaedt = args.wheel
228+
wheel_pyaedt = args.wheel
195229
import zipfile
196-
unzipped_path = os.path.join(os.path.dirname(wheelpyaedt),
197-
os.path.splitext(os.path.basename(wheelpyaedt))[0])
230+
unzipped_path = os.path.join(os.path.dirname(wheel_pyaedt),
231+
os.path.splitext(os.path.basename(wheel_pyaedt))[0])
198232
if os.path.exists(unzipped_path):
199233
shutil.rmtree(unzipped_path, ignore_errors=True)
200-
with zipfile.ZipFile(wheelpyaedt, 'r') as zip_ref:
201-
# Extract all contents to a directory (you can specify a different extraction path if needed)
234+
with zipfile.ZipFile(wheel_pyaedt, 'r') as zip_ref:
235+
# Extract all contents to a directory. (You can specify a different extraction path if needed.)
202236
zip_ref.extractall(unzipped_path)
203237

204238
run_command('"{}" install --no-cache-dir --no-index --find-links={} pyaedt'.format(pip_exe, unzipped_path))
@@ -224,9 +258,8 @@ def run_command(command):
224258

225259
if __name__ == "__main__":
226260

227-
# When launched from Toolkit (i.e. IronPython) call this same file using CPython
228261
if is_iron_python:
229-
# Check if wheelhouse defined, wheelhouse is created for Windows only
262+
# Check if wheelhouse defined. Wheelhouse is created for Windows only.
230263
wheelpyaedt = []
231264
# Retrieve the script arguments
232265
script_args = ScriptArgument.split()

ignore_words.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ aline
3232
COM
3333
gRPC
3434
Toolkits
35+
Extensions

0 commit comments

Comments
 (0)