Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c4b5a01
FEAT: Add 'panels' command to manage PyAEDT panels in AEDT + tests
eblanco-ansys Nov 17, 2025
2260ff6
chore: adding changelog file 6886.added.md [dependabot-skip]
pyansys-ci-bot Nov 17, 2025
80feb19
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Nov 17, 2025
d25c9a2
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
61804ed
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
f204e50
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
6a80835
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
a754c5b
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
1d1af83
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
99707a1
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
254aad1
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
1633128
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
08af825
Update src/ansys/aedt/core/cli.py
eblanco-ansys Nov 17, 2025
aa36ea8
Fixed unit tests
eblanco-ansys Nov 18, 2025
89d24e3
Merge branch 'main' into feat/cli-add-panels
eblanco-ansys Nov 18, 2025
e3204de
Unit test fix
eblanco-ansys Nov 18, 2025
50232db
Fixed unit tests
eblanco-ansys Nov 18, 2025
b5a4a4e
Decorate tests with patch
eblanco-ansys Nov 20, 2025
4f53938
Added automatic version detection
eblanco-ansys Nov 21, 2025
9ee7309
Merge branch 'main' into feat/cli-add-panels
eblanco-ansys Nov 21, 2025
6e5302e
Panels tests
eblanco-ansys Nov 21, 2025
93c1b53
Minor fixes
eblanco-ansys Nov 21, 2025
74e1120
Merge branch 'main' into feat/cli-add-panels
eblanco-ansys Nov 21, 2025
f26068a
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Nov 21, 2025
5d0bfb4
Fixed unit test
eblanco-ansys Nov 22, 2025
6f8622b
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Nov 22, 2025
dfcb7da
Improved code coverage
eblanco-ansys Nov 24, 2025
f547dcb
CHORE: Auto fixes from pre-commit hooks
pre-commit-ci[bot] Nov 24, 2025
3a4b732
Merge branch 'main' into feat/cli-add-panels
Samuelopez-ansys Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/6886.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add panels command to manage PyAEDT panels in AEDT + tests
209 changes: 196 additions & 13 deletions src/ansys/aedt/core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

import psutil

from ansys.aedt.core.internal.aedt_versions import aedt_versions

try:
import typer
except ImportError: # pragma: no cover
Expand Down Expand Up @@ -80,18 +82,6 @@ def _get_tests_folder() -> Path:
typer.echo("! Error finding tests folder, fallbacking to current working directory.")
# Fallback: search from current working directory
cwd = Path.cwd()
if cwd.name == "tests":
return cwd

tests_folder = cwd / "tests"
if tests_folder.exists():
return tests_folder

for parent in [cwd] + list(cwd.parents):
tests_folder = parent / "tests"
if tests_folder.exists():
return tests_folder

return cwd / "tests"


Expand Down Expand Up @@ -225,6 +215,10 @@ def _display_config(config: dict, title: str = "Configuration", descriptions: di
typer.echo()


panels_app = typer.Typer(help="Manage PyAEDT panels in AEDT", no_args_is_help=True)
app.add_typer(panels_app, name="panels")


def _is_valid_process(proc: psutil.Process) -> bool:
"""Check if a process is a valid AEDT process.

Expand Down Expand Up @@ -652,7 +646,7 @@ def processes():

@app.command()
def start(
version: str = typer.Option("2025.2", "--version", "-v", help="AEDT version to start (e.g., 2025.1, 2025.2)"),
version: str = typer.Option("2025.2", "--version", "-v", help="AEDT version to start (latest 2025.2)"),
non_graphical: bool = typer.Option(False, "--non-graphical", "-ng", help="Start AEDT in non-graphical mode"),
port: int = typer.Option(0, "--port", "-p", help="Port for AEDT connection (0 for auto)"),
student_version: bool = typer.Option(False, "--student", help="Start AEDT Student version"),
Expand Down Expand Up @@ -813,5 +807,194 @@ def stop(
return


@panels_app.command("add")
def add_panels(
aedt_version: str = typer.Option(
None,
"--version",
"-v",
help="AEDT version (such as 2025.2). If not provided, you'll be prompted to select from installed versions.",
),
personal_lib: str = typer.Option(
None,
"--personal-lib",
"-p",
help="Path to AEDT PersonalLib folder",
prompt="Enter path to PersonalLib folder",
),
skip_version_manager: bool = typer.Option(
False,
"--skip-version-manager",
help="Skip installing the Version Manager tab",
),
):
"""Add PyAEDT panels to AEDT installation.

This command installs PyAEDT tabs (Console, Jupyter, Run Script, Extension Manager,
and optionally Version Manager) into your AEDT installation.

Examples
--------
pyaedt panels add --version 2025.2 --personal-lib "C:\\Users\\username\\AppData\\Roaming\\Ansoft\\PersonalLib"
pyaedt panels add -v 2025.2 -p "/home/username/Ansoft/PersonalLib"
pyaedt panels add # Interactive mode: select from installed versions
"""
try:
installed = aedt_versions.installed_versions

if not installed:
typer.secho(
"✗ No AEDT versions found on this system.",
fg=typer.colors.RED,
bold=True,
)
typer.echo("\nPlease install AEDT before running this command.")
raise typer.Exit(code=1)

main_versions = [v for v in installed.keys() if not any(suffix in v for suffix in ["AWP", "CL", "SV"])]

if not main_versions:
main_versions = list(installed.keys())

if not aedt_version:
typer.secho("\nInstalled AEDT versions:", fg=typer.colors.CYAN, bold=True)
for idx, ver in enumerate(main_versions, 1):
typer.echo(f" {idx}. {ver}")

selection = typer.prompt("\nSelect AEDT version number", type=int, default=1)

if selection < 1 or selection > len(main_versions):
typer.secho(
f"✗ Invalid selection. Please choose a number between 1 and {len(main_versions)}.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)

aedt_version = main_versions[selection - 1]
typer.secho(f"\nSelected version: {aedt_version}", fg=typer.colors.GREEN)

# Validate AEDT version format
if not aedt_version or not isinstance(aedt_version, str):
typer.secho(
"✗ Invalid AEDT version. Provide a valid version string (such as 2025.2)",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)

aedt_version = aedt_version.strip()
if not aedt_version:
typer.secho("✗ AEDT version cannot be empty.", fg=typer.colors.RED, bold=True)
raise typer.Exit(code=1)

# Validate that the selected version is installed
if aedt_version not in installed:
typer.secho(
f"✗ AEDT version '{aedt_version}' is not installed on this system.",
fg=typer.colors.RED,
bold=True,
)
typer.echo("\nInstalled versions:")
for ver in main_versions:
typer.secho(f" • {ver}", fg=typer.colors.CYAN)
raise typer.Exit(code=1)

# Validate personal_lib path
if not personal_lib or not isinstance(personal_lib, str):
typer.secho(
"✗ the 'personal_lib' path is invalid. Provide a valid path",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)

personal_lib = personal_lib.strip()
if not personal_lib:
typer.secho(
"✗ The 'personal_lib' path is invalid. Provide a valid path.",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)

personal_lib_path = Path(personal_lib)

if not personal_lib_path.exists():
typer.secho(
f"✗ The 'personal_lib' path does not exist: {personal_lib_path}",
fg=typer.colors.RED,
bold=True,
)
typer.echo("\nCommon PersonalLib locations:")
if platform.system() == "Windows":
typer.secho(
" Windows: C:\\Users\\<username>\\AppData\\Roaming\\Ansoft\\PersonalLib",
fg=typer.colors.CYAN,
)
else:
typer.secho(
" Linux: /home/<username>/Ansoft/PersonalLib",
fg=typer.colors.CYAN,
)
raise typer.Exit(code=1)

if not personal_lib_path.is_dir():
typer.secho(
f"✗ The 'personallib' path is not a directory: {personal_lib_path}",
fg=typer.colors.RED,
bold=True,
)
raise typer.Exit(code=1)

# Import and run the installer
typer.secho(
f"Installing PyAEDT panels for AEDT {aedt_version}...",
fg=typer.colors.BLUE,
bold=True,
)
typer.secho(f"PersonalLib location: {personal_lib_path}", fg=typer.colors.CYAN)

if skip_version_manager:
typer.secho("Skipping Version Manager tab...", fg=typer.colors.YELLOW)

from ansys.aedt.core.extensions.installer.pyaedt_installer import add_pyaedt_to_aedt

result = add_pyaedt_to_aedt(
aedt_version=aedt_version,
personal_lib=str(personal_lib_path),
skip_version_manager=skip_version_manager,
odesktop=None,
)

if result is False:
typer.secho("✗ Failed to install PyAEDT panels.", fg=typer.colors.RED, bold=True)
raise typer.Exit(code=1)

typer.secho("✓ PyAEDT panels installed successfully.", fg=typer.colors.GREEN, bold=True)
typer.echo("\nInstalled panels:")
typer.secho(" • Console", fg=typer.colors.GREEN)
typer.secho(" • Jupyter", fg=typer.colors.GREEN)
typer.secho(" • Run Script", fg=typer.colors.GREEN)
typer.secho(" • Extension Manager", fg=typer.colors.GREEN)
if not skip_version_manager:
typer.secho(" • Version Manager", fg=typer.colors.GREEN)
typer.secho(
"\nRestart AEDT to see the new panels on the Automation tab.",
fg=typer.colors.YELLOW,
bold=True,
)

except typer.Exit:
raise
except ImportError as e:
typer.secho(f"✗ Import error: {str(e)}", fg=typer.colors.RED, bold=True)
typer.echo("Make sure PyAEDT is properly installed.")
raise typer.Exit(code=1)
except Exception as e:
typer.secho(f"✗ Error installing panels: {str(e)}", fg=typer.colors.RED, bold=True)
raise typer.Exit(code=1)


if __name__ == "__main__":
app()
Loading
Loading