Addon Manager: Black reformat
This commit is contained in:
@@ -49,6 +49,7 @@ INTERNAL_WORKBENCHES["sketcher"] = "Sketcher"
|
||||
INTERNAL_WORKBENCHES["spreadsheet"] = "Spreadsheet"
|
||||
INTERNAL_WORKBENCHES["techdraw"] = "TechDraw"
|
||||
|
||||
|
||||
class Addon:
|
||||
"Encapsulate information about a FreeCAD addon"
|
||||
|
||||
@@ -96,10 +97,10 @@ class Addon:
|
||||
|
||||
class Dependencies:
|
||||
def __init__(self):
|
||||
self.required_external_addons = [] # A list of Addons
|
||||
self.blockers = [] # A list of Addons
|
||||
self.replaces = [] # A list of Addons
|
||||
self.internal_workbenches: Set[str] = set() # Required internal workbenches
|
||||
self.required_external_addons = [] # A list of Addons
|
||||
self.blockers = [] # A list of Addons
|
||||
self.replaces = [] # A list of Addons
|
||||
self.internal_workbenches: Set[str] = set() # Required internal workbenches
|
||||
self.python_required: Set[str] = set()
|
||||
self.python_optional: Set[str] = set()
|
||||
|
||||
@@ -131,7 +132,9 @@ class Addon:
|
||||
# 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"):
|
||||
self.url = parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path[:-4]
|
||||
self.url = (
|
||||
parsed_url.scheme + "://" + parsed_url.netloc + parsed_url.path[:-4]
|
||||
)
|
||||
if parsed_url.query:
|
||||
self.url += "?" + parsed_url.query
|
||||
if parsed_url.fragment:
|
||||
@@ -241,9 +244,7 @@ class Addon:
|
||||
metadata = FreeCAD.Metadata(file)
|
||||
self.set_metadata(metadata)
|
||||
else:
|
||||
FreeCAD.Console.PrintLog(
|
||||
"Internal error: {} does not exist".format(file)
|
||||
)
|
||||
FreeCAD.Console.PrintLog("Internal error: {} does not exist".format(file))
|
||||
|
||||
def set_metadata(self, metadata: FreeCAD.Metadata) -> None:
|
||||
self.metadata = metadata
|
||||
@@ -271,23 +272,31 @@ class Addon:
|
||||
if dep_fc_min and dep_fc_min != "0.0.0":
|
||||
required_version = dep_fc_min.split(".")
|
||||
if fc_major < int(required_version[0]):
|
||||
return False # Major version is too low
|
||||
return False # Major version is too low
|
||||
elif fc_major == int(required_version[0]):
|
||||
if len(required_version) > 1 and fc_minor < int(required_version[1]):
|
||||
return False # Same major, and minor is too low
|
||||
if len(required_version) > 1 and fc_minor < int(
|
||||
required_version[1]
|
||||
):
|
||||
return False # Same major, and minor is too low
|
||||
except ValueError:
|
||||
FreeCAD.Console.PrintMessage(f"Metadata file for {self.name} has invalid FreeCADMin version info\n")
|
||||
FreeCAD.Console.PrintMessage(
|
||||
f"Metadata file for {self.name} has invalid FreeCADMin version info\n"
|
||||
)
|
||||
|
||||
try:
|
||||
if dep_fc_max and dep_fc_max != "0.0.0":
|
||||
required_version = dep_fc_max.split(".")
|
||||
if fc_major > int(required_version[0]):
|
||||
return False # Major version is too high
|
||||
return False # Major version is too high
|
||||
elif fc_major == int(required_version[0]):
|
||||
if len(required_version) > 1 and fc_minor > int(required_version[1]):
|
||||
return False # Same major, and minor is too high
|
||||
if len(required_version) > 1 and fc_minor > int(
|
||||
required_version[1]
|
||||
):
|
||||
return False # Same major, and minor is too high
|
||||
except ValueError:
|
||||
FreeCAD.Console.PrintMessage(f"Metadata file for {self.name} has invalid FreeCADMax version info\n")
|
||||
FreeCAD.Console.PrintMessage(
|
||||
f"Metadata file for {self.name} has invalid FreeCADMax version info\n"
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
@@ -301,7 +310,9 @@ class Addon:
|
||||
for dep in metadata.Depend:
|
||||
# Simple version for now: eventually support all of the version params...
|
||||
self.requires.add(dep["package"])
|
||||
FreeCAD.Console.PrintLog(f"Package {self.name}: Adding dependency on {dep['package']}\n")
|
||||
FreeCAD.Console.PrintLog(
|
||||
f"Package {self.name}: Adding dependency on {dep['package']}\n"
|
||||
)
|
||||
for dep in metadata.Conflict:
|
||||
self.blocks.add(dep["package"])
|
||||
|
||||
@@ -457,7 +468,7 @@ class Addon:
|
||||
elif dep.upper().endswith("WORKBENCH"):
|
||||
real_name = dep[:-9].strip().lower()
|
||||
else:
|
||||
real_name = dep.strip().lower()
|
||||
real_name = dep.strip().lower()
|
||||
|
||||
if real_name in INTERNAL_WORKBENCHES:
|
||||
deps.internal_workbenches.add(INTERNAL_WORKBENCHES[real_name])
|
||||
|
||||
@@ -259,7 +259,7 @@ class CommandAddonManager:
|
||||
self.dialog = FreeCADGui.PySideUic.loadUi(
|
||||
os.path.join(os.path.dirname(__file__), "AddonManager.ui")
|
||||
)
|
||||
#self.dialog.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True)
|
||||
# self.dialog.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True)
|
||||
|
||||
# cleanup the leftovers from previous runs
|
||||
self.macro_repo_dir = FreeCAD.getUserMacroDir(True)
|
||||
@@ -568,7 +568,7 @@ class CommandAddonManager:
|
||||
self.startup_sequence.append(self.load_macro_metadata)
|
||||
selection = pref.GetString("SelectedAddon", "")
|
||||
if selection:
|
||||
self.startup_sequence.insert(2,lambda:self.select_addon(selection))
|
||||
self.startup_sequence.insert(2, lambda: self.select_addon(selection))
|
||||
pref.SetString("SelectedAddon", "")
|
||||
self.current_progress_region = 0
|
||||
self.number_of_progress_regions = len(self.startup_sequence)
|
||||
@@ -755,7 +755,7 @@ class CommandAddonManager:
|
||||
else:
|
||||
self.do_next_startup_phase()
|
||||
|
||||
def select_addon(self, name:str) -> None:
|
||||
def select_addon(self, name: str) -> None:
|
||||
found = False
|
||||
for addon in self.item_model.repos:
|
||||
if addon.name == name:
|
||||
@@ -763,7 +763,11 @@ class CommandAddonManager:
|
||||
found = True
|
||||
break
|
||||
if not found:
|
||||
FreeCAD.Console.PrintWarning(translate("AddonsInstaller","Could not find addon '{}' to select\n").format(name))
|
||||
FreeCAD.Console.PrintWarning(
|
||||
translate(
|
||||
"AddonsInstaller", "Could not find addon '{}' to select\n"
|
||||
).format(name)
|
||||
)
|
||||
self.do_next_startup_phase()
|
||||
|
||||
def check_updates(self) -> None:
|
||||
@@ -930,7 +934,7 @@ class CommandAddonManager:
|
||||
self.item_model.append_item(repo)
|
||||
|
||||
# @dataclass(frozen)
|
||||
class MissingDependencies():
|
||||
class MissingDependencies:
|
||||
"""Encapsulates a group of four types of dependencies:
|
||||
* Internal workbenches -> wbs
|
||||
* External addons -> external_addons
|
||||
@@ -995,7 +999,7 @@ class CommandAddonManager:
|
||||
if option not in self.python_required
|
||||
]
|
||||
|
||||
def handle_disallowed_python(self, python_required:List[str]) -> bool:
|
||||
def handle_disallowed_python(self, python_required: List[str]) -> bool:
|
||||
"""Determine if we are missing any required Python packages that are not in the allowed
|
||||
packages list. If so, display a message to the user, and return True. Otherwise return
|
||||
False."""
|
||||
@@ -1009,16 +1013,22 @@ class CommandAddonManager:
|
||||
python_required.remove(dep)
|
||||
|
||||
if bad_packages:
|
||||
message = "<p>" + translate(
|
||||
"AddonsInstaller",
|
||||
"This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually:",
|
||||
) + "</p><ul>"
|
||||
message = (
|
||||
"<p>"
|
||||
+ translate(
|
||||
"AddonsInstaller",
|
||||
"This addon requires Python packages that are not installed, and cannot be installed automatically. To use this workbench you must install the following Python packages manually:",
|
||||
)
|
||||
+ "</p><ul>"
|
||||
)
|
||||
if len(bad_packages) < 15:
|
||||
for dep in bad_packages:
|
||||
message += f"<li>{dep}</li>"
|
||||
else:
|
||||
message += (
|
||||
"<li>(" + translate("AddonsInstaller", "Too many to list") + ")</li>"
|
||||
"<li>("
|
||||
+ translate("AddonsInstaller", "Too many to list")
|
||||
+ ")</li>"
|
||||
)
|
||||
message += "</ul>"
|
||||
message += "To ignore this error and install anyway, press OK."
|
||||
@@ -1046,7 +1056,7 @@ class CommandAddonManager:
|
||||
else:
|
||||
return False
|
||||
|
||||
def report_missing_workbenches(self, addon_name:str, wbs) -> bool:
|
||||
def report_missing_workbenches(self, addon_name: str, wbs) -> bool:
|
||||
if len(wbs) == 1:
|
||||
name = wbs[0]
|
||||
message = translate(
|
||||
@@ -1054,10 +1064,14 @@ class CommandAddonManager:
|
||||
"Addon '{}' requires '{}', which is not available in your copy of FreeCAD.",
|
||||
).format(addon_name, name)
|
||||
else:
|
||||
message = "<p>" + translate(
|
||||
"AddonsInstaller",
|
||||
"Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD:",
|
||||
).format(addon_name) + "</p><ul>"
|
||||
message = (
|
||||
"<p>"
|
||||
+ translate(
|
||||
"AddonsInstaller",
|
||||
"Addon '{}' requires the following workbenches, which are not available in your copy of FreeCAD:",
|
||||
).format(addon_name)
|
||||
+ "</p><ul>"
|
||||
)
|
||||
for wb in wbs:
|
||||
message += "<li>" + wb + "</li>"
|
||||
message += "</ul>"
|
||||
@@ -1075,9 +1089,7 @@ class CommandAddonManager:
|
||||
|
||||
def display_dep_resolution_dialog(self, missing, repo: Addon) -> None:
|
||||
self.dependency_dialog = FreeCADGui.PySideUic.loadUi(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__), "dependency_resolution_dialog.ui"
|
||||
)
|
||||
os.path.join(os.path.dirname(__file__), "dependency_resolution_dialog.ui")
|
||||
)
|
||||
self.dependency_dialog.setWindowFlag(QtCore.Qt.WindowStaysOnTopHint, True)
|
||||
|
||||
@@ -1109,13 +1121,18 @@ class CommandAddonManager:
|
||||
missing = CommandAddonManager.MissingDependencies(repo, self.item_model.repos)
|
||||
if self.handle_disallowed_python(missing.python_required):
|
||||
return
|
||||
|
||||
|
||||
good_packages = []
|
||||
for dep in missing.python_optional:
|
||||
if dep in self.allowed_packages:
|
||||
good_packages.append(dep)
|
||||
else:
|
||||
FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "Optional dependency on {} ignored because it is not in the allow-list\n").format(dep))
|
||||
FreeCAD.Console.PrintWarning(
|
||||
translate(
|
||||
"AddonsInstaller",
|
||||
"Optional dependency on {} ignored because it is not in the allow-list\n",
|
||||
).format(dep)
|
||||
)
|
||||
missing.python_optional = good_packages
|
||||
|
||||
if missing.wbs:
|
||||
|
||||
@@ -1326,7 +1326,16 @@ class DependencyInstallationWorker(QtCore.QThread):
|
||||
if QtCore.QThread.currentThread().isInterruptionRequested():
|
||||
return
|
||||
proc = subprocess.run(
|
||||
[python_exe, "-m", "pip", "install", "--disable-pip-version-check", "--target", vendor_path, pymod],
|
||||
[
|
||||
python_exe,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--disable-pip-version-check",
|
||||
"--target",
|
||||
vendor_path,
|
||||
pymod,
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
|
||||
@@ -46,6 +46,7 @@ def ask_to_install_toolbar_button(repo: Addon) -> None:
|
||||
)
|
||||
add_toolbar_button_dialog.exec()
|
||||
|
||||
|
||||
def check_for_button(repo: Addon) -> bool:
|
||||
command = FreeCADGui.Command.findCustomCommand(repo.macro.filename)
|
||||
if not command:
|
||||
@@ -60,6 +61,7 @@ def check_for_button(repo: Addon) -> bool:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def ask_for_toolbar(
|
||||
repo: Addon, custom_toolbars
|
||||
) -> object: # Returns the pref group for the new toolbar
|
||||
|
||||
@@ -500,14 +500,26 @@ class PackageDetails(QWidget):
|
||||
self.ui.webView.load(QUrl(url))
|
||||
self.ui.urlBar.setText(url)
|
||||
else:
|
||||
self.ui.urlBar.setText("(" + translate("AddonsInstaller", "No URL or wiki page provided by this macro") + ")")
|
||||
self.ui.urlBar.setText(
|
||||
"("
|
||||
+ translate(
|
||||
"AddonsInstaller", "No URL or wiki page provided by this macro"
|
||||
)
|
||||
+ ")"
|
||||
)
|
||||
else:
|
||||
if url:
|
||||
readme_data = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url)
|
||||
text = readme_data.data().decode("utf8")
|
||||
self.ui.textBrowserReadMe.setHtml(text)
|
||||
else:
|
||||
self.ui.textBrowserReadMe.setHtml("(" + translate("AddonsInstaller", "No URL or wiki page provided by this macro") + ")")
|
||||
self.ui.textBrowserReadMe.setHtml(
|
||||
"("
|
||||
+ translate(
|
||||
"AddonsInstaller", "No URL or wiki page provided by this macro"
|
||||
)
|
||||
+ ")"
|
||||
)
|
||||
|
||||
def run_javascript(self):
|
||||
"""Modify the page for a README to optimize for viewing in a smaller window"""
|
||||
|
||||
Reference in New Issue
Block a user