Skip to content

Commit

Permalink
Addon Manager: pylint cleanup in startup workers
Browse files Browse the repository at this point in the history
  • Loading branch information
chennes committed Aug 10, 2022
1 parent 20047c9 commit 9250850
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 36 deletions.
Expand Up @@ -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
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
98 changes: 64 additions & 34 deletions src/Mod/AddonManager/addonmanager_workers_startup.py
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -434,14 +441,18 @@ 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):
QtCore.QThread.__init__(self)
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:
Expand All @@ -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)
Expand All @@ -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:
Expand All @@ -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")
Expand All @@ -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
Expand Down Expand Up @@ -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):

Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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...")
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/AddonManager/package_details.py
Expand Up @@ -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
Expand Down

0 comments on commit 9250850

Please sign in to comment.