From 2245c6f79131213fa524ceb5c7efe402d52a1679 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Wed, 10 Jul 2024 15:09:37 -0700 Subject: [PATCH 1/9] Dependency module update --- exporter/SynthesisFusionAddin/Synthesis.py | 17 ++- .../SynthesisFusionAddin/src/Dependencies.py | 143 ++++++++++++++++++ 2 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 exporter/SynthesisFusionAddin/src/Dependencies.py diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 335a2416ce..75a8242da0 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -6,11 +6,18 @@ import adsk.core -from .src.configure import setAnalytics, unload_config -from .src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm, root_logger -from .src.Types.OString import OString -from .src.UI import HUI, Camera, ConfigCommand, Handlers, Helper, MarkingMenu -from .src.UI.Toolbar import Toolbar +from .src.Dependencies import resolveDependencies + +try: + from .src.configure import setAnalytics, unload_config + from .src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm, root_logger + from .src.Types.OString import OString + from .src.UI import HUI, Camera, ConfigCommand, Handlers, Helper, MarkingMenu + from .src.UI.Toolbar import Toolbar +except (ImportError, ModuleNotFoundError): + # Dependency likely has not been installed OR protobuf files were not compiled and could not be found. + resolveDependencies() + adsk.core.Application.get().userInterface.messageBox("Installed required dependencies, please restart Fusion.") def run(_): diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py new file mode 100644 index 0000000000..73e03343c3 --- /dev/null +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -0,0 +1,143 @@ +import importlib.machinery +import logging +import os +import platform +import subprocess +import sys +from pathlib import Path + +import adsk.core +import adsk.fusion + +from .general_imports import INTERNAL_ID + +logger = logging.getLogger(INTERNAL_ID) +system = platform.system() + +# Since the Fusion python runtime is separate from the system python runtime we need to do some funky things +# in order to download and install python packages separate from the standard library. +PIP_DEPENDENCY_VERSION_MAP: dict[str, str] = { + "protobuf": "5.27.2", +} + + +# TODO: Waiting on GH-1010 for failure logging. +def getInternalFusionPythonInstillationFolder() -> str: + # Thank you Kris Kaplan + # Find the folder location where the Autodesk python instillation keeps the 'os' standard library module. + pythonStandardLibraryModulePath = importlib.machinery.PathFinder.find_spec("os", sys.path).origin + + # Depending on platform, adjust to folder to where the python executable binaries are stored. + if system == "Windows": + folder = f"{Path(pythonStandardLibraryModulePath).parents[1]}" + elif system == "Darwin": + folder = f"{Path(pythonStandardLibraryModulePath).parents[2]}/bin" + else: + # TODO: System string should be moved to __init__ after GH-1013 + raise RuntimeError("Unsupported platform.") + + return folder + + +def executeCommand(*args: str) -> subprocess.CompletedProcess: + logger.debug(f"Running Command -> {' '.join(args)}") + try: + result: subprocess.CompletedProcess = subprocess.run( + args, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True + ) + logger.debug(f"Command Output:\n{result.stdout}") + return result + + except subprocess.CalledProcessError as error: + logger.error(f"Exit code: {error.returncode}") + logger.error(f"Output:\n{error.stderr}") + raise error + + +def verifyCompiledProtoImports() -> bool: + try: + from ..proto.proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 + + return True + except ImportError: + # TODO: Add logging from GH-1010 + return False + + +def getInstalledPipPackages(pythonExecutablePath: str) -> dict[str, str]: + result: str = executeCommand(pythonExecutablePath, "-m", "pip", "freeze").stdout + # We don't need to check against packages with a specific hash as those are not required by Synthesis. + return {x.split("==")[0]: x.split("==")[1] for x in result.splitlines() if "==" in x} + + +def packagesOutOfDate(installedPackages: dict[str, str]) -> bool: + for package, installedVersion in installedPackages.items(): + expectedVersion = PIP_DEPENDENCY_VERSION_MAP.get(package) + if expectedVersion and expectedVersion != installedVersion: + return True + + return False + + +# TODO: GH-1010 for log failure +def resolveDependencies() -> None: + app = adsk.core.Application.get() + ui = app.userInterface + if app.isOffLine: + # If we have gotten this far that means that an import error was thrown for possible missing + # dependencies... And we can't try to download them because we have no internet... ¯\_(ツ)_/¯ + ui.messageBox("Unable to resolve dependencies while not connected to the internet.") + raise RuntimeError("Internet required to check dependencies") + + # This is important to reduce the chance of hang on startup. + adsk.doEvents() + + pythonFolder = getInternalFusionPythonInstillationFolder() + pythonExecutableFile = "python.exe" if system == "Windows" else "python" # Confirming 110% everything is fine. + pythonExecutablePath = os.path.join(pythonFolder, pythonExecutableFile) + + progressBar = ui.createProgressDialog() + progressBar.isCancelButtonShown = False + progressBar.reset() + progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP), 0) + + # TODO: Is this really true? Do we need this? waheusnta eho? - Brandon + # Install pip manually on macos as it is not included by default? Really? + if system == "Darwin" and not os.path.exists(os.path.join(pythonFolder, "pip")): + pipInstallScriptPath = os.path.join(pythonFolder, "get-pip.py") + if not os.path.exists(pipInstallScriptPath): + executeCommand("curl", "https://bootstrap.pypa.io/get-pip.py", "-o", pipInstallScriptPath) + progressBar.maximumValue += 2 + progressBar.progressValue += 1 + progressBar.message = "Downloading PIP Installer..." + + progressBar.progressValue += 1 + progressBar.message = "Installing PIP..." + executeCommand(pythonExecutablePath, pipInstallScriptPath) + + installedPackages = getInstalledPipPackages(pythonExecutablePath) + if packagesOutOfDate(installedPackages): + # Uninstall and reinstall everything to confirm updated versions. + progressBar.message = "Uninstalling out-of-date Dependencies..." + progressBar.maximumValue += len(PIP_DEPENDENCY_VERSION_MAP) + + for dep in PIP_DEPENDENCY_VERSION_MAP.keys(): + progressBar.progressValue += 1 + executeCommand(pythonExecutablePath, "-m", "pip", "uninstall", "-y", dep) + + progressBar.message = "Installing Dependencies..." + for dep, version in PIP_DEPENDENCY_VERSION_MAP.items(): + progressBar.progressValue += 1 + progressBar.message = f"Installing {dep}..." + adsk.doEvents() + + # TODO: Will need to update logging after GH-1010 + result = executeCommand(pythonExecutablePath, "-m", "pip", "install", f"{dep}=={version}").returncode + if result: + logging.getLogger(f"{INTERNAL_ID}").warn(f'Dep installation "{dep}" exited with code "{result}"') + + progressBar.hide() + + # TODO: Will need to update logging after GH-1010 + if not verifyCompiledProtoImports(): + ui.messageBox("Missing required compiled protobuf files.") From cee612d7f73ebd61aa16401235c4ca71991e24ec Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Fri, 26 Jul 2024 16:25:34 -0700 Subject: [PATCH 2/9] Integration with GH-1010 --- exporter/SynthesisFusionAddin/Synthesis.py | 8 ++---- .../SynthesisFusionAddin/src/Dependencies.py | 27 +++++++++---------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 0b3a4e3bf2..370a52830f 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -8,6 +8,7 @@ from .src.Dependencies import resolveDependencies try: + from .src.APS import APS from .src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm from .src.Logging import getLogger, logFailure, setupLogger from .src.UI import ( @@ -20,12 +21,7 @@ ShowAPSAuthCommand, ) from .src.UI.Toolbar import Toolbar - - # END OF RESTRICTION - # Transition: AARD-1721 - # Should attempt to fix this ordering scheme within AARD-1741 - from .src.APS import APS # isort:skip -except: +except (ImportError, ModuleNotFoundError): result = resolveDependencies() if result: adsk.core.Application.get().userInterface.messageBox("Installed required dependencies, please restart Fusion.") diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index bd4d71a454..7dac67294c 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -1,5 +1,4 @@ import importlib.machinery -import logging import os import platform import subprocess @@ -9,19 +8,20 @@ import adsk.core import adsk.fusion -from .general_imports import INTERNAL_ID +from .Logging import getLogger, logFailure -logger = logging.getLogger(INTERNAL_ID) +logger = getLogger() system = platform.system() # Since the Fusion python runtime is separate from the system python runtime we need to do some funky things # in order to download and install python packages separate from the standard library. PIP_DEPENDENCY_VERSION_MAP: dict[str, str] = { "protobuf": "5.27.2", + "requests": "2.32.3", } -# TODO: Waiting on GH-1010 for failure logging. +@logFailure def getInternalFusionPythonInstillationFolder() -> str: # Thank you Kris Kaplan # Find the folder location where the Autodesk python instillation keeps the 'os' standard library module. @@ -60,7 +60,7 @@ def verifyCompiledProtoImports() -> bool: return True except ImportError: - # TODO: Add logging from GH-1010 + logger.warn("Could not resolve compiled proto dependencies") return False @@ -79,15 +79,19 @@ def packagesOutOfDate(installedPackages: dict[str, str]) -> bool: return False -# TODO: GH-1010 for log failure +@logFailure def resolveDependencies() -> bool | None: app = adsk.core.Application.get() ui = app.userInterface + if not verifyCompiledProtoImports(): + ui.messageBox("Missing required compiled protobuf files.") + return False + if app.isOffLine: # If we have gotten this far that means that an import error was thrown for possible missing # dependencies... And we can't try to download them because we have no internet... ¯\_(ツ)_/¯ ui.messageBox("Unable to resolve dependencies while not connected to the internet.") - raise RuntimeError("Internet required to check dependencies") + return False # This is important to reduce the chance of hang on startup. adsk.doEvents() @@ -131,16 +135,9 @@ def resolveDependencies() -> bool | None: progressBar.message = f"Installing {dep}..." adsk.doEvents() - # TODO: Will need to update logging after GH-1010 result = executeCommand(pythonExecutablePath, "-m", "pip", "install", f"{dep}=={version}").returncode if result: - logging.getLogger(f"{INTERNAL_ID}").warn(f'Dep installation "{dep}" exited with code "{result}"') + logger.warn(f'Dep installation "{dep}" exited with code "{result}"') progressBar.hide() - - # TODO: Will need to update logging after GH-1010 - if not verifyCompiledProtoImports(): - ui.messageBox("Missing required compiled protobuf files.") - return False - return True From a723159098b0560a766493fa175f8ff0ec6762e1 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 30 Jul 2024 08:53:40 -0700 Subject: [PATCH 3/9] Better import verification --- exporter/SynthesisFusionAddin/Synthesis.py | 21 +++++++++------ .../SynthesisFusionAddin/src/Dependencies.py | 26 ++++++++++++++----- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 370a52830f..7a691b4789 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -1,16 +1,21 @@ -# DO NOT CHANGE ORDER, OR ADD IMPORTS BEFORE UNTIL END COMMENT - import os -from shutil import rmtree import adsk.core -from .src.Dependencies import resolveDependencies +# Currently required for `resolveDependencies()`, will be required for absolute imports. +# sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +from .src.Dependencies import resolveDependencies # isort:skip + +# Transition: AARD-1741 +# Import order should be removed in AARD-1737 and `setupLogger()` moved to `__init__.py` +from .src.Logging import getLogger, logFailure, setupLogger # isort:skip + +setupLogger() try: from .src.APS import APS from .src.general_imports import APP_NAME, DESCRIPTION, INTERNAL_ID, gm - from .src.Logging import getLogger, logFailure, setupLogger from .src.UI import ( HUI, Camera, @@ -21,10 +26,11 @@ ShowAPSAuthCommand, ) from .src.UI.Toolbar import Toolbar -except (ImportError, ModuleNotFoundError): +except (ImportError, ModuleNotFoundError) as error: + getLogger().warn(f"Running resolve dependencies with error of:\n{error}") result = resolveDependencies() if result: - adsk.core.Application.get().userInterface.messageBox("Installed required dependencies, please restart Fusion.") + adsk.core.Application.get().userInterface.messageBox("Installed required dependencies.\nPlease restart Fusion.") @logFailure @@ -34,7 +40,6 @@ def run(_): Arguments: **context** *context* -- Fusion context to derive app and UI. """ - setupLogger() # Remove all items prior to start just to make sure unregister_all() diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index 7dac67294c..b508571b49 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -1,4 +1,5 @@ import importlib.machinery +import importlib.util import os import platform import subprocess @@ -54,14 +55,15 @@ def executeCommand(*args: str) -> subprocess.CompletedProcess: raise error +@logFailure def verifyCompiledProtoImports() -> bool: - try: - from ..proto.proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 + protoModules = ["assembly_pb2", "joint_pb2", "material_pb2", "types_pb2"] + for module in protoModules: + spec = importlib.util.find_spec(f"proto.proto_out.{module}") + if spec is None: + return False - return True - except ImportError: - logger.warn("Could not resolve compiled proto dependencies") - return False + return True def getInstalledPipPackages(pythonExecutablePath: str) -> dict[str, str]: @@ -141,3 +143,15 @@ def resolveDependencies() -> bool | None: progressBar.hide() return True + + +# Transition: AARD-1741 +# Extra function included here for debugging purposes, this function can be deleted upon verification +# that everything is working correctly as it can be easily constructed later. +def uninstallPipDependencies() -> None: + pythonFolder = getInternalFusionPythonInstillationFolder() + pythonExecutableFile = "python.exe" if system == "Windows" else "python" # Confirming 110% everything is fine. + pythonExecutablePath = os.path.join(pythonFolder, pythonExecutableFile) + for dep in PIP_DEPENDENCY_VERSION_MAP.keys(): + executeCommand(pythonExecutablePath, "-m", "pip", "uninstall", "-y", dep) + logger.debug(f"Uninstalled {dep}") From 517369b84515b45d98478c90e78f178c143ced40 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 30 Jul 2024 08:54:31 -0700 Subject: [PATCH 4/9] Removed old deps file --- exporter/SynthesisFusionAddin/proto/deps.py | 191 -------------------- 1 file changed, 191 deletions(-) delete mode 100644 exporter/SynthesisFusionAddin/proto/deps.py diff --git a/exporter/SynthesisFusionAddin/proto/deps.py b/exporter/SynthesisFusionAddin/proto/deps.py deleted file mode 100644 index 10ec7757b3..0000000000 --- a/exporter/SynthesisFusionAddin/proto/deps.py +++ /dev/null @@ -1,191 +0,0 @@ -import os -import platform -from pathlib import Path - -import adsk.core -import adsk.fusion - -from src.Logging import getLogger, logFailure - -system = platform.system() -logger = getLogger() - - -@logFailure(messageBox=True) -def getPythonFolder() -> str: - """Retreives the folder that contains the Autodesk python executable - - Raises: - ImportError: Unrecognized Platform - - Returns: - str: The path that contains the Autodesk python executable - """ - - # Thank you Kris Kaplan - import importlib.machinery - import sys - - osPath = importlib.machinery.PathFinder.find_spec("os", sys.path).origin - - # The location of the python executable is found relative to the location of the os module in each operating system - if system == "Windows": - pythonFolder = Path(osPath).parents[1] - elif system == "Darwin": - pythonFolder = f"{Path(osPath).parents[2]}/bin" - else: - raise ImportError("Unsupported platform! This add-in only supports windows and macos") - - logger.debug(f"Python Folder -> {pythonFolder}") - return pythonFolder - - -def executeCommand(command: tuple) -> int: - """Abstracts the execution of commands to account for platform differences - - Args: - command (tuple): Tuple starting with command, and each indice having the arguments for said command - - Returns: - int: Exit code of the process - """ - - joinedCommand = str.join(" ", command) - logger.debug(f"Command -> {joinedCommand}") - executionResult = os.system(joinedCommand) - - return executionResult - - -@logFailure(messageBox=True) -def installCross(pipDeps: list) -> bool: - """Attempts to fetch pip script and resolve dependencies with less user interaction - - Args: - pipDeps (list): List of all string imports - - Returns: - bool: Success - - Notes: - Liam originally came up with this style after realizing accessing the python dir was too unreliable. - """ - app = adsk.core.Application.get() - ui = app.userInterface - - if app.isOffLine: - ui.messageBox( - "Unable to install dependencies when Fusion is offline. Please connect to the internet and try again!" - ) - return False - - progressBar = ui.createProgressDialog() - progressBar.isCancelButtonShown = False - progressBar.reset() - progressBar.show("Synthesis", f"Installing dependencies...", 0, len(pipDeps), 0) - - # this is important to reduce the chance of hang on startup - adsk.doEvents() - - try: - pythonFolder = getPythonFolder() - except ImportError as e: - logger.error(f"Failed to download dependencies: {e.msg}") - return False - - if system == "Darwin": # macos - # if nothing has previously fetched it - if not os.path.exists(f"{pythonFolder}/get-pip.py"): - executeCommand( - [ - "curl", - "https://bootstrap.pypa.io/get-pip.py", - "-o", - f'"{pythonFolder}/get-pip.py"', - ] - ) - - executeCommand([f'"{pythonFolder}/python"', f'"{pythonFolder}/get-pip.py"']) - - pythonExecutable = "python" - if system == "Windows": - pythonExecutable = "python.exe" - - for depName in pipDeps: - progressBar.progressValue += 1 - progressBar.message = f"Installing {depName}..." - adsk.doEvents() - - # os.path.join needed for varying system path separators - installResult = executeCommand( - [ - f'"{os.path.join(pythonFolder, pythonExecutable)}"', - "-m", - "pip", - "install", - depName, - ] - ) - if installResult != 0: - logger.warn(f'Dep installation "{depName}" exited with code "{installResult}"') - - if system == "Darwin": - pipAntiDeps = ["dataclasses", "typing"] - progressBar.progressValue = 0 - progressBar.maximumValue = len(pipAntiDeps) - for depName in pipAntiDeps: - progressBar.message = f"Uninstalling {depName}..." - progressBar.progressValue += 1 - adsk.doEvents() - uninstallResult = executeCommand( - [ - f'"{os.path.join(pythonFolder, pythonExecutable)}"', - "-m", - "pip", - "uninstall", - f"{depName}", - "-y", - ] - ) - if uninstallResult != 0: - logger.warn(f'AntiDep uninstallation "{depName}" exited with code "{uninstallResult}"') - - progressBar.hide() - - if _checkDeps(): - return True - else: - # Will be caught and logged to a message box & log file from `@logFailure` - raise RuntimeError("Failed to install dependencies needed") - - -def _checkDeps() -> bool: - try: - from .proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 - - return True - except ImportError: - return False - - -""" -Checks for, and installs if need be, the dependencies needed by the Synthesis Exporter. Will error if it cannot install the dependencies -correctly. This should crash the exporter, since most of the exporter needs these dependencies to function in -the first place. -""" - - -def installDependencies(): - try: - import logging.handlers - - import google.protobuf - import pkg_resources - from requests import get, post - - from .proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 - except ImportError or ModuleNotFoundError: - installCross(["protobuf==4.23.3", "requests==2.32.3"]) - from requests import get, post - - from .proto_out import assembly_pb2, joint_pb2, material_pb2, types_pb2 From 46b278b0b73b02427c2d452b2b169532f1526b7b Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 30 Jul 2024 09:02:49 -0700 Subject: [PATCH 5/9] Uncomment add import path --- exporter/SynthesisFusionAddin/Synthesis.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index 7a691b4789..f5e8b250b7 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -1,9 +1,10 @@ import os +import sys import adsk.core # Currently required for `resolveDependencies()`, will be required for absolute imports. -# sys.path.append(os.path.dirname(os.path.abspath(__file__))) +sys.path.append(os.path.dirname(os.path.abspath(__file__))) from .src.Dependencies import resolveDependencies # isort:skip From a601ededf3123e2156dcc1b4cd5e23469e4ba9c9 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 30 Jul 2024 09:59:05 -0700 Subject: [PATCH 6/9] Final cleanups --- exporter/SynthesisFusionAddin/Synthesis.py | 2 +- exporter/SynthesisFusionAddin/src/Dependencies.py | 9 +++++---- exporter/SynthesisFusionAddin/src/general_imports.py | 5 ----- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index f5e8b250b7..c7e0072f4e 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -6,7 +6,7 @@ # Currently required for `resolveDependencies()`, will be required for absolute imports. sys.path.append(os.path.dirname(os.path.abspath(__file__))) -from .src.Dependencies import resolveDependencies # isort:skip +from .src.Dependencies import resolveDependencies, uninstallPipDependencies # isort:skip # Transition: AARD-1741 # Import order should be removed in AARD-1737 and `setupLogger()` moved to `__init__.py` diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index b508571b49..e4726ba52e 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -59,6 +59,7 @@ def executeCommand(*args: str) -> subprocess.CompletedProcess: def verifyCompiledProtoImports() -> bool: protoModules = ["assembly_pb2", "joint_pb2", "material_pb2", "types_pb2"] for module in protoModules: + # Absolute imports must be set up by this point for importlib to be able to find each module. spec = importlib.util.find_spec(f"proto.proto_out.{module}") if spec is None: return False @@ -105,7 +106,7 @@ def resolveDependencies() -> bool | None: progressBar = ui.createProgressDialog() progressBar.isCancelButtonShown = False progressBar.reset() - progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP), 0) + progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP) * 2 + 2, 0) # TODO: Is this really true? Do we need this? waheusnta eho? - Brandon # Install pip manually on macos as it is not included by default? Really? @@ -113,23 +114,23 @@ def resolveDependencies() -> bool | None: pipInstallScriptPath = os.path.join(pythonFolder, "get-pip.py") if not os.path.exists(pipInstallScriptPath): executeCommand("curl", "https://bootstrap.pypa.io/get-pip.py", "-o", pipInstallScriptPath) - progressBar.maximumValue += 2 - progressBar.progressValue += 1 progressBar.message = "Downloading PIP Installer..." progressBar.progressValue += 1 progressBar.message = "Installing PIP..." executeCommand(pythonExecutablePath, pipInstallScriptPath) + progressBar.progressValue += 1 installedPackages = getInstalledPipPackages(pythonExecutablePath) if packagesOutOfDate(installedPackages): # Uninstall and reinstall everything to confirm updated versions. progressBar.message = "Uninstalling out-of-date Dependencies..." - progressBar.maximumValue += len(PIP_DEPENDENCY_VERSION_MAP) for dep in PIP_DEPENDENCY_VERSION_MAP.keys(): progressBar.progressValue += 1 executeCommand(pythonExecutablePath, "-m", "pip", "uninstall", "-y", dep) + else: + progressBar.progressValue += len(PIP_DEPENDENCY_VERSION_MAP) progressBar.message = "Installing Dependencies..." for dep, version in PIP_DEPENDENCY_VERSION_MAP.items(): diff --git a/exporter/SynthesisFusionAddin/src/general_imports.py b/exporter/SynthesisFusionAddin/src/general_imports.py index 67d5e3b3cc..aabdae5cac 100644 --- a/exporter/SynthesisFusionAddin/src/general_imports.py +++ b/exporter/SynthesisFusionAddin/src/general_imports.py @@ -31,11 +31,6 @@ if not path_proto_files in sys.path: sys.path.insert(2, path_proto_files) - - from proto import deps - - deps.installDependencies() - except: logger.error("Failed:\n{}".format(traceback.format_exc())) From 08e96960d28eaee721f00ffa70f3cb1e9c4f9d96 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 30 Jul 2024 10:00:01 -0700 Subject: [PATCH 7/9] Remove unused function --- exporter/SynthesisFusionAddin/Synthesis.py | 2 +- exporter/SynthesisFusionAddin/src/Dependencies.py | 14 +------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/exporter/SynthesisFusionAddin/Synthesis.py b/exporter/SynthesisFusionAddin/Synthesis.py index c7e0072f4e..f5e8b250b7 100644 --- a/exporter/SynthesisFusionAddin/Synthesis.py +++ b/exporter/SynthesisFusionAddin/Synthesis.py @@ -6,7 +6,7 @@ # Currently required for `resolveDependencies()`, will be required for absolute imports. sys.path.append(os.path.dirname(os.path.abspath(__file__))) -from .src.Dependencies import resolveDependencies, uninstallPipDependencies # isort:skip +from .src.Dependencies import resolveDependencies # isort:skip # Transition: AARD-1741 # Import order should be removed in AARD-1737 and `setupLogger()` moved to `__init__.py` diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index e4726ba52e..99dc216020 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -106,7 +106,7 @@ def resolveDependencies() -> bool | None: progressBar = ui.createProgressDialog() progressBar.isCancelButtonShown = False progressBar.reset() - progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP) * 2 + 2, 0) + progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP * 2 + 2), 0) # TODO: Is this really true? Do we need this? waheusnta eho? - Brandon # Install pip manually on macos as it is not included by default? Really? @@ -144,15 +144,3 @@ def resolveDependencies() -> bool | None: progressBar.hide() return True - - -# Transition: AARD-1741 -# Extra function included here for debugging purposes, this function can be deleted upon verification -# that everything is working correctly as it can be easily constructed later. -def uninstallPipDependencies() -> None: - pythonFolder = getInternalFusionPythonInstillationFolder() - pythonExecutableFile = "python.exe" if system == "Windows" else "python" # Confirming 110% everything is fine. - pythonExecutablePath = os.path.join(pythonFolder, pythonExecutableFile) - for dep in PIP_DEPENDENCY_VERSION_MAP.keys(): - executeCommand(pythonExecutablePath, "-m", "pip", "uninstall", "-y", dep) - logger.debug(f"Uninstalled {dep}") From 8c565ed0180383ce30d467d9e806faf72af66ec7 Mon Sep 17 00:00:00 2001 From: BrandonPacewic Date: Tue, 30 Jul 2024 10:36:24 -0700 Subject: [PATCH 8/9] Syntax fix got lost somehow --- exporter/SynthesisFusionAddin/src/Dependencies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index 99dc216020..f55643dfae 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -106,7 +106,7 @@ def resolveDependencies() -> bool | None: progressBar = ui.createProgressDialog() progressBar.isCancelButtonShown = False progressBar.reset() - progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP * 2 + 2), 0) + progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP) * 2 + 2, 0) # TODO: Is this really true? Do we need this? waheusnta eho? - Brandon # Install pip manually on macos as it is not included by default? Really? From 459c8ff524692c243aca3184d5c6fd1f1353aa29 Mon Sep 17 00:00:00 2001 From: Brandon Pacewic Date: Wed, 31 Jul 2024 14:45:42 -0700 Subject: [PATCH 9/9] Remove confirmed `TODO` --- exporter/SynthesisFusionAddin/src/Dependencies.py | 1 - 1 file changed, 1 deletion(-) diff --git a/exporter/SynthesisFusionAddin/src/Dependencies.py b/exporter/SynthesisFusionAddin/src/Dependencies.py index f55643dfae..b9ad31f7be 100644 --- a/exporter/SynthesisFusionAddin/src/Dependencies.py +++ b/exporter/SynthesisFusionAddin/src/Dependencies.py @@ -108,7 +108,6 @@ def resolveDependencies() -> bool | None: progressBar.reset() progressBar.show("Synthesis", f"Installing dependencies...", 0, len(PIP_DEPENDENCY_VERSION_MAP) * 2 + 2, 0) - # TODO: Is this really true? Do we need this? waheusnta eho? - Brandon # Install pip manually on macos as it is not included by default? Really? if system == "Darwin" and not os.path.exists(os.path.join(pythonFolder, "pip")): pipInstallScriptPath = os.path.join(pythonFolder, "get-pip.py")