Addon Manager: Clean up Addon.py based on pylint

This commit is contained in:
Chris Hennes
2022-07-27 15:39:35 -05:00
parent b1856f3603
commit 802993dc5d

View File

@@ -20,15 +20,19 @@
# * *
# ***************************************************************************
import FreeCAD
""" Defines the Addon class to encapsulate information about FreeCAD Addons """
import os
from urllib.parse import urlparse
from typing import Dict, Set
from threading import Lock
from enum import IntEnum
import FreeCAD
from addonmanager_macro import Macro
import addonmanager_utilities as utils
from addonmanager_utilities import construct_git_url
translate = FreeCAD.Qt.translate
@@ -51,11 +55,11 @@ INTERNAL_WORKBENCHES["techdraw"] = "TechDraw"
class Addon:
"Encapsulate information about a FreeCAD addon"
from enum import IntEnum
"""Encapsulates information about a FreeCAD addon"""
class Kind(IntEnum):
"""The type of Addon: Workbench, macro, or package"""
WORKBENCH = 1
MACRO = 2
PACKAGE = 3
@@ -63,12 +67,15 @@ class Addon:
def __str__(self) -> str:
if self.value == 1:
return "Workbench"
elif self.value == 2:
if self.value == 2:
return "Macro"
elif self.value == 3:
if self.value == 3:
return "Package"
return "ERROR_TYPE"
class Status(IntEnum):
"""The installation status of an Addon"""
NOT_INSTALLED = 0
UNCHECKED = 1
NO_UPDATE_AVAILABLE = 2
@@ -82,20 +89,26 @@ class Addon:
return NotImplemented
def __str__(self) -> str:
result = ""
if self.value == 0:
return "Not installed"
result = "Not installed"
elif self.value == 1:
return "Unchecked"
result = "Unchecked"
elif self.value == 2:
return "No update available"
result = "No update available"
elif self.value == 3:
return "Update available"
result = "Update available"
elif self.value == 4:
return "Restart required"
result = "Restart required"
elif self.value == 5:
return "Can't check"
result = "Can't check"
else:
result = "ERROR_STATUS"
return result
class Dependencies:
"""Addon dependency information"""
def __init__(self):
self.required_external_addons = [] # A list of Addons
self.blockers = [] # A list of Addons
@@ -105,8 +118,7 @@ class Addon:
self.python_optional: Set[str] = set()
class ResolutionFailed(RuntimeError):
def __init__(self, msg):
super().__init__(msg)
"""An exception type for dependency resolution failure."""
def __init__(self, name: str, url: str, status: Status, branch: str):
self.name = name.strip()
@@ -127,8 +139,6 @@ class Addon:
self.status_lock = Lock()
self.set_status(status)
from addonmanager_utilities import construct_git_url
# The url should never end in ".git", so strip it if it's there
parsed_url = urlparse(self.url)
if parsed_url.path.endswith(".git"):
@@ -172,7 +182,9 @@ class Addon:
return result
@classmethod
def from_macro(self, macro: Macro):
def from_macro(cls, macro: Macro):
"""Create an Addon object from a Macro wrapper object"""
if macro.is_installed():
status = Addon.Status.UNCHECKED
else:
@@ -184,7 +196,7 @@ class Addon:
return instance
@classmethod
def from_cache(self, cache_dict: Dict):
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"])
@@ -240,13 +252,18 @@ class Addon:
}
def load_metadata_file(self, file: str) -> None:
"""Read a given metadata file and set it as this object's metadata"""
if os.path.exists(file):
metadata = FreeCAD.Metadata(file)
self.set_metadata(metadata)
else:
FreeCAD.Console.PrintLog("Internal error: {} does not exist".format(file))
FreeCAD.Console.PrintLog(f"Internal error: {file} does not exist")
def set_metadata(self, metadata: FreeCAD.Metadata) -> None:
"""Set the given metadata object as this object's metadata, updating the object's display name
and package type information to match, as well as updating any dependency information, etc."""
self.metadata = metadata
self.display_name = metadata.Name
self.repo_type = Addon.Kind.PACKAGE
@@ -262,6 +279,9 @@ class Addon:
self.extract_metadata_dependencies(self.metadata)
def version_is_ok(self, metadata) -> bool:
"""Checks to see if the current running version of FreeCAD meets the requirements set by
the passed-in metadata parameter."""
dep_fc_min = metadata.FreeCADMin
dep_fc_max = metadata.FreeCADMax
@@ -273,7 +293,7 @@ class Addon:
required_version = dep_fc_min.split(".")
if fc_major < int(required_version[0]):
return False # Major version is too low
elif fc_major == int(required_version[0]):
if fc_major == int(required_version[0]):
if len(required_version) > 1 and fc_minor < int(
required_version[1]
):
@@ -288,7 +308,7 @@ class Addon:
required_version = dep_fc_max.split(".")
if fc_major > int(required_version[0]):
return False # Major version is too high
elif fc_major == int(required_version[0]):
if fc_major == int(required_version[0]):
if len(required_version) > 1 and fc_minor > int(
required_version[1]
):
@@ -301,6 +321,7 @@ class Addon:
return True
def extract_metadata_dependencies(self, metadata):
"""Read dependency information from a metadata object and store it in this Addon"""
# Version check: if this piece of metadata doesn't apply to this version of
# FreeCAD, just skip it.
@@ -345,6 +366,7 @@ class Addon:
)
def extract_tags(self, metadata: FreeCAD.Metadata) -> None:
"""Read the tags from the metadata object"""
# Version check: if this piece of metadata doesn't apply to this version of
# FreeCAD, just skip it.
@@ -355,7 +377,7 @@ class Addon:
self.tags.add(new_tag)
content = metadata.Content
for key, value in content.items():
for _, value in content.items():
for item in value:
self.extract_tags(item)
@@ -364,7 +386,7 @@ class Addon:
if self.repo_type == Addon.Kind.WORKBENCH:
return True
elif self.repo_type == Addon.Kind.PACKAGE:
if self.repo_type == Addon.Kind.PACKAGE:
if self.metadata is None:
FreeCAD.Console.PrintLog(
f"Addon Manager internal error: lost metadata for package {self.name}\n"
@@ -377,15 +399,14 @@ class Addon:
)
return False
return "workbench" in content
else:
return False
return False
def contains_macro(self) -> bool:
"""Determine if this package contains (or is) a macro"""
if self.repo_type == Addon.Kind.MACRO:
return True
elif self.repo_type == Addon.Kind.PACKAGE:
if self.repo_type == Addon.Kind.PACKAGE:
if self.metadata is None:
FreeCAD.Console.PrintLog(
f"Addon Manager internal error: lost metadata for package {self.name}\n"
@@ -393,8 +414,7 @@ class Addon:
return False
content = self.metadata.Content
return "macro" in content
else:
return False
return False
def contains_preference_pack(self) -> bool:
"""Determine if this package contains a preference pack"""
@@ -407,8 +427,7 @@ class Addon:
return False
content = self.metadata.Content
return "preferencepack" in content
else:
return False
return False
def get_cached_icon_filename(self) -> str:
"""Get the filename for the locally-cached copy of the icon"""
@@ -481,37 +500,41 @@ class Addon:
deps.blockers[dep] = all_repos[dep]
def status(self):
"""Threadsafe access to the current update status"""
with self.status_lock:
return self.update_status
def set_status(self, status):
"""Threadsafe setting of the update status"""
with self.status_lock:
self.update_status = status
def is_disabled(self):
# Check for existence of disabling stopfile:
"""Check to see if the disabling stopfile exists"""
stopfile = os.path.join(
FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED"
)
if os.path.exists(stopfile):
return True
else:
return False
return os.path.exists(stopfile)
def disable(self):
"""Disable this addon from loading when FreeCAD starts up by creating a stopfile"""
stopfile = os.path.join(
FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED"
)
with open(stopfile, "w") as f:
with open(stopfile, "w", encoding="utf-8") as f:
f.write(
"The existence of this file prevents FreeCAD from loading this Addon. To re-enable, delete the file."
)
def enable(self):
"""Re-enable loading this addon by deleting the stopfile"""
stopfile = os.path.join(
FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED"
)
try:
os.unlink(stopfile)
except Exception:
except FileNotFoundError:
pass