From 9250850c9c058dde7caa73c82c16dfaefc1d75b4 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Wed, 10 Aug 2022 09:17:02 -0500 Subject: [PATCH] Addon Manager: pylint cleanup in startup workers --- .../gui/test_workers_startup.py | 11 ++- .../addonmanager_workers_startup.py | 98 ++++++++++++------- src/Mod/AddonManager/package_details.py | 2 +- 3 files changed, 75 insertions(+), 36 deletions(-) diff --git a/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py b/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py index 7a2957b927b0..e92007e85287 100644 --- a/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py +++ b/src/Mod/AddonManager/AddonManagerTest/gui/test_workers_startup.py @@ -154,4 +154,13 @@ def test_load_macros_from_cache_worker(self): def _macro_added_from_cache(self, addon:Addon): """ Callback for adding macros from the cache """ print (f"Macro Cache Test: {addon.name}") - self.macro_from_cache_counter += 1 \ No newline at end of file + self.macro_from_cache_counter += 1 + + def test_update_checker(self): + """ Test the code that checks a single addon for available updates. """ + + # First, install a specific Addon of each kind + + # Arrange for those addons to be out-of-date + + # Check for updates \ No newline at end of file diff --git a/src/Mod/AddonManager/addonmanager_workers_startup.py b/src/Mod/AddonManager/addonmanager_workers_startup.py index b98763db8aba..f0c18c8bbd0e 100644 --- a/src/Mod/AddonManager/addonmanager_workers_startup.py +++ b/src/Mod/AddonManager/addonmanager_workers_startup.py @@ -83,6 +83,7 @@ def __init__(self): self.package_names = [] self.moddir = os.path.join(FreeCAD.getUserAppDataDir(), "Mod") + self.current_thread = None def run(self): "populates the list of addons" @@ -118,32 +119,7 @@ def _get_freecad_addon_repo_data(self): self.py2only = j["py2only"]["Mod"] if "deprecated" in j: - fc_major = int(FreeCAD.Version()[0]) - fc_minor = int(FreeCAD.Version()[1]) - for item in j["deprecated"]: - if "as_of" in item and "name" in item: - try: - version_components = item["as_of"].split(".") - major = int(version_components[0]) - if len(version_components) > 1: - minor = int(version_components[1]) - else: - minor = 0 - if major < fc_major or ( - major == fc_major and minor <= fc_minor - ): - if "kind" not in item or item["kind"] == "mod": - self.obsolete.append(item["name"]) - elif item["kind"] == "macro": - self.macros_reject_list.append(item["name"]) - else: - FreeCAD.Console.PrintMessage( - f'Unrecognized Addon kind {item["kind"]} in deprecation list.' - ) - except Exception: - FreeCAD.Console.PrintMessage( - f"Exception caught when parsing deprecated Addon {item['name']}, version {item['as_of']}" - ) + self._process_deprecated(j["deprecated"]) else: message = translate( @@ -154,6 +130,36 @@ def _get_freecad_addon_repo_data(self): self.status_message.emit(message) raise ConnectionError + def _process_deprecated(self, deprecated_addons): + """ Parse the section on deprecated addons """ + + fc_major = int(FreeCAD.Version()[0]) + fc_minor = int(FreeCAD.Version()[1]) + for item in deprecated_addons: + if "as_of" in item and "name" in item: + try: + version_components = item["as_of"].split(".") + major = int(version_components[0]) + if len(version_components) > 1: + minor = int(version_components[1]) + else: + minor = 0 + if major < fc_major or ( + major == fc_major and minor <= fc_minor + ): + if "kind" not in item or item["kind"] == "mod": + self.obsolete.append(item["name"]) + elif item["kind"] == "macro": + self.macros_reject_list.append(item["name"]) + else: + FreeCAD.Console.PrintMessage( + f'Unrecognized Addon kind {item["kind"]} in deprecation list.' + ) + except Exception: + FreeCAD.Console.PrintMessage( + f"Exception caught when parsing deprecated Addon {item['name']}, version {item['as_of']}" + ) + def _get_custom_addons(self): # querying custom addons first @@ -308,13 +314,13 @@ def _retrieve_macros_from_git(self): FreeCAD.Console.PrintMessage( translate("AddonsInstaller", "Clean checkout succeeded") + "\n" ) - except Exception as e: + except Exception as e2: FreeCAD.Console.PrintWarning( translate( "AddonsInstaller", "Failed to update macros from GitHub -- try clearing the Addon Manager's cache.", ) - + f":\n{str(e)}\n" + + f":\n{str(e2)}\n" ) return n_files = 0 @@ -408,6 +414,7 @@ def override_metadata_cache_path(self, path): self.metadata_cache_path = path def run(self): + """ Rarely called directly: create an instance and call start() on it instead to launch in a new thread """ with open(self.cache_file, "r", encoding="utf-8") as f: data = f.read() if data: @@ -434,6 +441,8 @@ def run(self): class LoadMacrosFromCacheWorker(QtCore.QThread): + """ A worker object to load macros from a cache file """ + add_macro_signal = QtCore.Signal(object) def __init__(self, cache_file: str): @@ -441,7 +450,9 @@ def __init__(self, cache_file: str): self.cache_file = cache_file def run(self): - with open(self.cache_file, "r") as f: + """ Rarely called directly: create an instance and call start() on it instead to launch in a new thread """ + + with open(self.cache_file, "r", encoding="utf-8") as f: data = f.read() dict_data = json.loads(data) for item in dict_data: @@ -464,7 +475,9 @@ def __init__(self, repo: Addon, parent: QtCore.QObject = None): self.repo = repo def do_work(self): - # Borrow the function from another class: + """ Use the UpdateChecker class to do the work of this function, depending on the + type of Addon """ + checker = UpdateChecker() if self.repo.repo_type == Addon.Kind.WORKBENCH: checker.check_workbench(self.repo) @@ -486,12 +499,14 @@ def __init__(self, repos: List[Addon]): QtCore.QThread.__init__(self) self.repos = repos + self.current_thread = None + self.basedir = FreeCAD.getUserAppDataDir() + self.moddir = os.path.join(self.basedir, "Mod") def run(self): + """ Rarely called directly: create an instance and call start() on it instead to launch in a new thread """ self.current_thread = QtCore.QThread.currentThread() - self.basedir = FreeCAD.getUserAppDataDir() - self.moddir = os.path.join(self.basedir, "Mod") checker = UpdateChecker() count = 1 for repo in self.repos: @@ -512,6 +527,9 @@ def run(self): class UpdateChecker: + """ A utility class used by the CheckWorkbenchesForUpdatesWorker class. Each function is designed + for a specific Addon type, and modifies the passed-in Addon with the determined update status. """ + def __init__(self): self.basedir = FreeCAD.getUserAppDataDir() self.moddir = os.path.join(self.basedir, "Mod") @@ -521,6 +539,7 @@ def override_mod_directory(self, moddir): self.moddir = moddir def check_workbench(self, wb): + """ Given a workbench Addon wb, check it for updates using git. If git is not available, does nothing. """ if not have_git or NOGIT: wb.set_status(Addon.Status.CANNOT_CHECK) return @@ -570,6 +589,10 @@ def check_workbench(self, wb): wb.set_status(Addon.Status.CANNOT_CHECK) def check_package(self, package: Addon) -> None: + """ Given a packaged Addon package, check it for updates. If git is available that is used. If not, + the package's metadata is examined, and if the metadata file has changed compared to the installed + copy, an update is flagged.""" + clonedir = self.moddir + os.sep + package.name if os.path.exists(clonedir): @@ -589,8 +612,7 @@ def check_package(self, package: Addon) -> None: package.set_status(Addon.Status.UPDATE_AVAILABLE) package.installed_version = None return - else: - package.updated_timestamp = os.path.getmtime(installed_metadata_file) + package.updated_timestamp = os.path.getmtime(installed_metadata_file) try: installed_metadata = FreeCAD.Metadata(installed_metadata_file) package.installed_version = installed_metadata.Version @@ -611,6 +633,8 @@ def check_package(self, package: Addon) -> None: package.set_status(Addon.Status.CANNOT_CHECK) def check_macro(self, macro_wrapper: Addon) -> None: + """ Check to see if the online copy of the macro's code differs from the local copy. """ + # Make sure this macro has its code downloaded: try: if not macro_wrapper.macro.parsed and macro_wrapper.macro.on_git: @@ -677,8 +701,11 @@ def __init__(self, repos: List[Addon]) -> None: self.lock = threading.Lock() self.failed = [] self.counter = 0 + self.repo_queue = None def run(self): + """ Rarely called directly: create an instance and call start() on it instead to launch in a new thread """ + self.status_message.emit(translate("AddonsInstaller", "Caching macro code...")) self.repo_queue = queue.Queue() @@ -741,6 +768,7 @@ def run(self): ) def update_and_advance(self, repo: Addon) -> None: + """ Emit the updated signal and launch the next item from the queue. """ if repo is not None: if repo.macro.name not in self.failed: self.update_macro.emit(repo) @@ -775,6 +803,7 @@ def update_and_advance(self, repo: Addon) -> None: pass def terminate(self, worker) -> None: + """ Shut down all running workers and exit the thread """ if not worker.isFinished(): macro_name = worker.macro.name FreeCAD.Console.PrintWarning( @@ -810,6 +839,7 @@ def __init__(self, repo): self.macro = repo.macro def run(self): + """ Rarely called directly: create an instance and call start() on it instead to launch in a new thread """ self.status_message.emit( translate("AddonsInstaller", "Retrieving macro description...") diff --git a/src/Mod/AddonManager/package_details.py b/src/Mod/AddonManager/package_details.py index e18ff9bbcf90..7c1075e0e43a 100644 --- a/src/Mod/AddonManager/package_details.py +++ b/src/Mod/AddonManager/package_details.py @@ -35,7 +35,7 @@ import FreeCADGui import addonmanager_utilities as utils -from addonmanager_workers import GetMacroDetailsWorker, CheckSingleUpdateWorker +from addonmanager_workers_startup import GetMacroDetailsWorker, CheckSingleUpdateWorker from Addon import Addon import NetworkManager from change_branch import ChangeBranchDialog