|
32 | 32 |
|
33 | 33 | import psutil |
34 | 34 |
|
| 35 | +from ansys.aedt.core.internal.aedt_versions import aedt_versions |
| 36 | + |
35 | 37 | try: |
36 | 38 | import typer |
37 | 39 | except ImportError: # pragma: no cover |
@@ -80,18 +82,6 @@ def _get_tests_folder() -> Path: |
80 | 82 | typer.echo("! Error finding tests folder, fallbacking to current working directory.") |
81 | 83 | # Fallback: search from current working directory |
82 | 84 | cwd = Path.cwd() |
83 | | - if cwd.name == "tests": |
84 | | - return cwd |
85 | | - |
86 | | - tests_folder = cwd / "tests" |
87 | | - if tests_folder.exists(): |
88 | | - return tests_folder |
89 | | - |
90 | | - for parent in [cwd] + list(cwd.parents): |
91 | | - tests_folder = parent / "tests" |
92 | | - if tests_folder.exists(): |
93 | | - return tests_folder |
94 | | - |
95 | 85 | return cwd / "tests" |
96 | 86 |
|
97 | 87 |
|
@@ -225,6 +215,10 @@ def _display_config(config: dict, title: str = "Configuration", descriptions: di |
225 | 215 | typer.echo() |
226 | 216 |
|
227 | 217 |
|
| 218 | +panels_app = typer.Typer(help="Manage PyAEDT panels in AEDT", no_args_is_help=True) |
| 219 | +app.add_typer(panels_app, name="panels") |
| 220 | + |
| 221 | + |
228 | 222 | def _is_valid_process(proc: psutil.Process) -> bool: |
229 | 223 | """Check if a process is a valid AEDT process. |
230 | 224 |
|
@@ -652,7 +646,7 @@ def processes(): |
652 | 646 |
|
653 | 647 | @app.command() |
654 | 648 | def start( |
655 | | - version: str = typer.Option("2025.2", "--version", "-v", help="AEDT version to start (e.g., 2025.1, 2025.2)"), |
| 649 | + version: str = typer.Option("2025.2", "--version", "-v", help="AEDT version to start (latest 2025.2)"), |
656 | 650 | non_graphical: bool = typer.Option(False, "--non-graphical", "-ng", help="Start AEDT in non-graphical mode"), |
657 | 651 | port: int = typer.Option(0, "--port", "-p", help="Port for AEDT connection (0 for auto)"), |
658 | 652 | student_version: bool = typer.Option(False, "--student", help="Start AEDT Student version"), |
@@ -813,5 +807,194 @@ def stop( |
813 | 807 | return |
814 | 808 |
|
815 | 809 |
|
| 810 | +@panels_app.command("add") |
| 811 | +def add_panels( |
| 812 | + aedt_version: str = typer.Option( |
| 813 | + None, |
| 814 | + "--version", |
| 815 | + "-v", |
| 816 | + help="AEDT version (such as 2025.2). If not provided, you'll be prompted to select from installed versions.", |
| 817 | + ), |
| 818 | + personal_lib: str = typer.Option( |
| 819 | + None, |
| 820 | + "--personal-lib", |
| 821 | + "-p", |
| 822 | + help="Path to AEDT PersonalLib folder", |
| 823 | + prompt="Enter path to PersonalLib folder", |
| 824 | + ), |
| 825 | + skip_version_manager: bool = typer.Option( |
| 826 | + False, |
| 827 | + "--skip-version-manager", |
| 828 | + help="Skip installing the Version Manager tab", |
| 829 | + ), |
| 830 | +): |
| 831 | + """Add PyAEDT panels to AEDT installation. |
| 832 | +
|
| 833 | + This command installs PyAEDT tabs (Console, Jupyter, Run Script, Extension Manager, |
| 834 | + and optionally Version Manager) into your AEDT installation. |
| 835 | +
|
| 836 | + Examples |
| 837 | + -------- |
| 838 | + pyaedt panels add --version 2025.2 --personal-lib "C:\\Users\\username\\AppData\\Roaming\\Ansoft\\PersonalLib" |
| 839 | + pyaedt panels add -v 2025.2 -p "/home/username/Ansoft/PersonalLib" |
| 840 | + pyaedt panels add # Interactive mode: select from installed versions |
| 841 | + """ |
| 842 | + try: |
| 843 | + installed = aedt_versions.installed_versions |
| 844 | + |
| 845 | + if not installed: |
| 846 | + typer.secho( |
| 847 | + "✗ No AEDT versions found on this system.", |
| 848 | + fg=typer.colors.RED, |
| 849 | + bold=True, |
| 850 | + ) |
| 851 | + typer.echo("\nPlease install AEDT before running this command.") |
| 852 | + raise typer.Exit(code=1) |
| 853 | + |
| 854 | + main_versions = [v for v in installed.keys() if not any(suffix in v for suffix in ["AWP", "CL", "SV"])] |
| 855 | + |
| 856 | + if not main_versions: |
| 857 | + main_versions = list(installed.keys()) |
| 858 | + |
| 859 | + if not aedt_version: |
| 860 | + typer.secho("\nInstalled AEDT versions:", fg=typer.colors.CYAN, bold=True) |
| 861 | + for idx, ver in enumerate(main_versions, 1): |
| 862 | + typer.echo(f" {idx}. {ver}") |
| 863 | + |
| 864 | + selection = typer.prompt("\nSelect AEDT version number", type=int, default=1) |
| 865 | + |
| 866 | + if selection < 1 or selection > len(main_versions): |
| 867 | + typer.secho( |
| 868 | + f"✗ Invalid selection. Please choose a number between 1 and {len(main_versions)}.", |
| 869 | + fg=typer.colors.RED, |
| 870 | + bold=True, |
| 871 | + ) |
| 872 | + raise typer.Exit(code=1) |
| 873 | + |
| 874 | + aedt_version = main_versions[selection - 1] |
| 875 | + typer.secho(f"\nSelected version: {aedt_version}", fg=typer.colors.GREEN) |
| 876 | + |
| 877 | + # Validate AEDT version format |
| 878 | + if not aedt_version or not isinstance(aedt_version, str): |
| 879 | + typer.secho( |
| 880 | + "✗ Invalid AEDT version. Provide a valid version string (such as 2025.2)", |
| 881 | + fg=typer.colors.RED, |
| 882 | + bold=True, |
| 883 | + ) |
| 884 | + raise typer.Exit(code=1) |
| 885 | + |
| 886 | + aedt_version = aedt_version.strip() |
| 887 | + if not aedt_version: |
| 888 | + typer.secho("✗ AEDT version cannot be empty.", fg=typer.colors.RED, bold=True) |
| 889 | + raise typer.Exit(code=1) |
| 890 | + |
| 891 | + # Validate that the selected version is installed |
| 892 | + if aedt_version not in installed: |
| 893 | + typer.secho( |
| 894 | + f"✗ AEDT version '{aedt_version}' is not installed on this system.", |
| 895 | + fg=typer.colors.RED, |
| 896 | + bold=True, |
| 897 | + ) |
| 898 | + typer.echo("\nInstalled versions:") |
| 899 | + for ver in main_versions: |
| 900 | + typer.secho(f" • {ver}", fg=typer.colors.CYAN) |
| 901 | + raise typer.Exit(code=1) |
| 902 | + |
| 903 | + # Validate personal_lib path |
| 904 | + if not personal_lib or not isinstance(personal_lib, str): |
| 905 | + typer.secho( |
| 906 | + "✗ the 'personal_lib' path is invalid. Provide a valid path", |
| 907 | + fg=typer.colors.RED, |
| 908 | + bold=True, |
| 909 | + ) |
| 910 | + raise typer.Exit(code=1) |
| 911 | + |
| 912 | + personal_lib = personal_lib.strip() |
| 913 | + if not personal_lib: |
| 914 | + typer.secho( |
| 915 | + "✗ The 'personal_lib' path is invalid. Provide a valid path.", |
| 916 | + fg=typer.colors.RED, |
| 917 | + bold=True, |
| 918 | + ) |
| 919 | + raise typer.Exit(code=1) |
| 920 | + |
| 921 | + personal_lib_path = Path(personal_lib) |
| 922 | + |
| 923 | + if not personal_lib_path.exists(): |
| 924 | + typer.secho( |
| 925 | + f"✗ The 'personal_lib' path does not exist: {personal_lib_path}", |
| 926 | + fg=typer.colors.RED, |
| 927 | + bold=True, |
| 928 | + ) |
| 929 | + typer.echo("\nCommon PersonalLib locations:") |
| 930 | + if platform.system() == "Windows": |
| 931 | + typer.secho( |
| 932 | + " Windows: C:\\Users\\<username>\\AppData\\Roaming\\Ansoft\\PersonalLib", |
| 933 | + fg=typer.colors.CYAN, |
| 934 | + ) |
| 935 | + else: |
| 936 | + typer.secho( |
| 937 | + " Linux: /home/<username>/Ansoft/PersonalLib", |
| 938 | + fg=typer.colors.CYAN, |
| 939 | + ) |
| 940 | + raise typer.Exit(code=1) |
| 941 | + |
| 942 | + if not personal_lib_path.is_dir(): |
| 943 | + typer.secho( |
| 944 | + f"✗ The 'personallib' path is not a directory: {personal_lib_path}", |
| 945 | + fg=typer.colors.RED, |
| 946 | + bold=True, |
| 947 | + ) |
| 948 | + raise typer.Exit(code=1) |
| 949 | + |
| 950 | + # Import and run the installer |
| 951 | + typer.secho( |
| 952 | + f"Installing PyAEDT panels for AEDT {aedt_version}...", |
| 953 | + fg=typer.colors.BLUE, |
| 954 | + bold=True, |
| 955 | + ) |
| 956 | + typer.secho(f"PersonalLib location: {personal_lib_path}", fg=typer.colors.CYAN) |
| 957 | + |
| 958 | + if skip_version_manager: |
| 959 | + typer.secho("Skipping Version Manager tab...", fg=typer.colors.YELLOW) |
| 960 | + |
| 961 | + from ansys.aedt.core.extensions.installer.pyaedt_installer import add_pyaedt_to_aedt |
| 962 | + |
| 963 | + result = add_pyaedt_to_aedt( |
| 964 | + aedt_version=aedt_version, |
| 965 | + personal_lib=str(personal_lib_path), |
| 966 | + skip_version_manager=skip_version_manager, |
| 967 | + odesktop=None, |
| 968 | + ) |
| 969 | + |
| 970 | + if result is False: |
| 971 | + typer.secho("✗ Failed to install PyAEDT panels.", fg=typer.colors.RED, bold=True) |
| 972 | + raise typer.Exit(code=1) |
| 973 | + |
| 974 | + typer.secho("✓ PyAEDT panels installed successfully.", fg=typer.colors.GREEN, bold=True) |
| 975 | + typer.echo("\nInstalled panels:") |
| 976 | + typer.secho(" • Console", fg=typer.colors.GREEN) |
| 977 | + typer.secho(" • Jupyter", fg=typer.colors.GREEN) |
| 978 | + typer.secho(" • Run Script", fg=typer.colors.GREEN) |
| 979 | + typer.secho(" • Extension Manager", fg=typer.colors.GREEN) |
| 980 | + if not skip_version_manager: |
| 981 | + typer.secho(" • Version Manager", fg=typer.colors.GREEN) |
| 982 | + typer.secho( |
| 983 | + "\nRestart AEDT to see the new panels on the Automation tab.", |
| 984 | + fg=typer.colors.YELLOW, |
| 985 | + bold=True, |
| 986 | + ) |
| 987 | + |
| 988 | + except typer.Exit: |
| 989 | + raise |
| 990 | + except ImportError as e: |
| 991 | + typer.secho(f"✗ Import error: {str(e)}", fg=typer.colors.RED, bold=True) |
| 992 | + typer.echo("Make sure PyAEDT is properly installed.") |
| 993 | + raise typer.Exit(code=1) |
| 994 | + except Exception as e: |
| 995 | + typer.secho(f"✗ Error installing panels: {str(e)}", fg=typer.colors.RED, bold=True) |
| 996 | + raise typer.Exit(code=1) |
| 997 | + |
| 998 | + |
816 | 999 | if __name__ == "__main__": |
817 | 1000 | app() |
0 commit comments