Addon Manager: Refactor to improve testability
This commit is contained in:
@@ -120,6 +120,12 @@ class Addon:
|
||||
class ResolutionFailed(RuntimeError):
|
||||
"""An exception type for dependency resolution failure."""
|
||||
|
||||
# The location of Addon Manager cache files: overridden by testing code
|
||||
cache_directory = os.path.join(FreeCAD.getUserCachePath(), "AddonManager")
|
||||
|
||||
# The location of the Mod directory: overridden by testing code
|
||||
mod_directory = os.path.join(FreeCAD.getUserAppDataDir(), "Mod")
|
||||
|
||||
def __init__(self, name: str, url: str, status: Status, branch: str):
|
||||
self.name = name.strip()
|
||||
self.display_name = self.name
|
||||
@@ -199,7 +205,7 @@ class Addon:
|
||||
def from_cache(cls, cache_dict: Dict):
|
||||
"""Load basic data from cached dict data. Does not include Macro or Metadata information, which must be populated separately."""
|
||||
|
||||
mod_dir = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", cache_dict["name"])
|
||||
mod_dir = os.path.join(cls.mod_directory, cache_dict["name"])
|
||||
if os.path.isdir(mod_dir):
|
||||
status = Addon.Status.UNCHECKED
|
||||
else:
|
||||
@@ -215,8 +221,7 @@ class Addon:
|
||||
if instance.repo_type == Addon.Kind.PACKAGE:
|
||||
# There must be a cached metadata file, too
|
||||
cached_package_xml_file = os.path.join(
|
||||
FreeCAD.getUserCachePath(),
|
||||
"AddonManager",
|
||||
instance.cache_directory,
|
||||
"PackageMetadata",
|
||||
instance.name,
|
||||
)
|
||||
@@ -458,7 +463,7 @@ class Addon:
|
||||
|
||||
_, file_extension = os.path.splitext(real_icon)
|
||||
store = os.path.join(
|
||||
FreeCAD.getUserCachePath(), "AddonManager", "PackageMetadata"
|
||||
self.cache_directory, "PackageMetadata"
|
||||
)
|
||||
self.cached_icon_filename = os.path.join(
|
||||
store, self.name, "cached_icon" + file_extension
|
||||
@@ -513,7 +518,7 @@ class Addon:
|
||||
"""Check to see if the disabling stopfile exists"""
|
||||
|
||||
stopfile = os.path.join(
|
||||
FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED"
|
||||
self.mod_directory, self.name, "ADDON_DISABLED"
|
||||
)
|
||||
return os.path.exists(stopfile)
|
||||
|
||||
@@ -521,7 +526,7 @@ class Addon:
|
||||
"""Disable this addon from loading when FreeCAD starts up by creating a stopfile"""
|
||||
|
||||
stopfile = os.path.join(
|
||||
FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED"
|
||||
mod_directory, self.name, "ADDON_DISABLED"
|
||||
)
|
||||
with open(stopfile, "w", encoding="utf-8") as f:
|
||||
f.write(
|
||||
@@ -532,7 +537,7 @@ class Addon:
|
||||
"""Re-enable loading this addon by deleting the stopfile"""
|
||||
|
||||
stopfile = os.path.join(
|
||||
FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED"
|
||||
self.mod_directory, self.name, "ADDON_DISABLED"
|
||||
)
|
||||
try:
|
||||
os.unlink(stopfile)
|
||||
|
||||
@@ -52,9 +52,18 @@ class TestWorkersStartup(unittest.TestCase):
|
||||
self.macro_counter = 0
|
||||
self.workbench_counter = 0
|
||||
self.prefpack_counter = 0
|
||||
|
||||
# Populated when the addon list is created in the first test
|
||||
self.package_cache = {}
|
||||
self.macro_cache = {}
|
||||
|
||||
self.package_cache_file = tempfile.NamedTemporaryFile(mode='w', encoding="utf-8", delete=False)
|
||||
self.macro_cache_file = tempfile.NamedTemporaryFile(mode='w', encoding="utf-8", delete=False)
|
||||
|
||||
def test_create_addon_list_worker(self):
|
||||
""" Test whether any addons are added: runs the full query, so this potentially is a SLOW test """
|
||||
""" Test whether any addons are added: runs the full query, so this potentially is a SLOW
|
||||
test. Note that this test must be run before any of the other tests, so that the cache gets
|
||||
created. """
|
||||
worker = CreateAddonListWorker()
|
||||
worker.addon_repo.connect(self._addon_added)
|
||||
worker.start()
|
||||
@@ -65,6 +74,14 @@ class TestWorkersStartup(unittest.TestCase):
|
||||
self.assertGreater(self.workbench_counter,0, "No workbenches returned")
|
||||
self.assertGreater(self.prefpack_counter,0, "No preference packs returned")
|
||||
|
||||
# Write the cache data
|
||||
if hasattr(self, "package_cache"):
|
||||
self.package_cache_file.write(json.dumps(self.package_cache, indent=" "))
|
||||
self.package_cache_file.close()
|
||||
if hasattr(self, "macro_cache"):
|
||||
self.macro_cache_file.write(json.dumps(self.macro_cache, indent=" "))
|
||||
self.macro_cache_file.close()
|
||||
|
||||
def _addon_added(self, addon:Addon):
|
||||
""" Callback for adding an Addon: tracks the list, and counts the various types """
|
||||
print (f"Addon Test: {addon.name}")
|
||||
@@ -76,3 +93,14 @@ class TestWorkersStartup(unittest.TestCase):
|
||||
if addon.contains_preference_pack():
|
||||
self.prefpack_counter += 1
|
||||
|
||||
# Also record the information for cache purposes
|
||||
self.package_cache[addon.name] = addon.to_cache()
|
||||
|
||||
if addon.macro is not None:
|
||||
self.macro_cache.append(addon.macro.to_cache())
|
||||
|
||||
def test_load_packages_from_cache_worker(self):
|
||||
pass
|
||||
|
||||
def test_load_macros_from_cache_worker(self):
|
||||
pass
|
||||
|
||||
@@ -393,16 +393,21 @@ class CreateAddonListWorker(QtCore.QThread):
|
||||
|
||||
|
||||
class LoadPackagesFromCacheWorker(QtCore.QThread):
|
||||
""" A subthread worker that loads package information from its cache file. """
|
||||
addon_repo = QtCore.Signal(object)
|
||||
|
||||
def __init__(self, cache_file: str):
|
||||
QtCore.QThread.__init__(self)
|
||||
self.cache_file = cache_file
|
||||
|
||||
def run(self):
|
||||
metadata_cache_path = os.path.join(
|
||||
self.metadata_cache_path = os.path.join(
|
||||
FreeCAD.getUserCachePath(), "AddonManager", "PackageMetadata"
|
||||
)
|
||||
|
||||
def override_metadata_cache_path(self, path):
|
||||
""" For testing purposes, override the location to fetch the package metadata from. """
|
||||
self.metadata_cache_path = path
|
||||
|
||||
def run(self):
|
||||
with open(self.cache_file, "r", encoding="utf-8") as f:
|
||||
data = f.read()
|
||||
if data:
|
||||
@@ -412,7 +417,7 @@ class LoadPackagesFromCacheWorker(QtCore.QThread):
|
||||
return
|
||||
repo = Addon.from_cache(item)
|
||||
repo_metadata_cache_path = os.path.join(
|
||||
metadata_cache_path, repo.name, "package.xml"
|
||||
self.metadata_cache_path, repo.name, "package.xml"
|
||||
)
|
||||
if os.path.isfile(repo_metadata_cache_path):
|
||||
try:
|
||||
@@ -511,6 +516,10 @@ class UpdateChecker:
|
||||
self.basedir = FreeCAD.getUserAppDataDir()
|
||||
self.moddir = os.path.join(self.basedir, "Mod")
|
||||
|
||||
def override_mod_directory(self, moddir):
|
||||
""" Primarily for use when testing, sets an alternate directory to use for mods """
|
||||
self.moddir = moddir
|
||||
|
||||
def check_workbench(self, wb):
|
||||
if not have_git or NOGIT:
|
||||
wb.set_status(Addon.Status.CANNOT_CHECK)
|
||||
|
||||
Reference in New Issue
Block a user