Merge pull request #9117 from Ondsel-Development/wb_pref_fixes

Wb pref fixes
This commit is contained in:
Chris Hennes
2023-04-04 14:05:47 -05:00
committed by GitHub
12 changed files with 321 additions and 95 deletions

View File

@@ -24,6 +24,7 @@
""" Defines the Addon class to encapsulate information about FreeCAD Addons """
import os
import re
from urllib.parse import urlparse
from typing import Dict, Set, List, Optional
from threading import Lock
@@ -592,6 +593,9 @@ class Addon:
"The existence of this file prevents FreeCAD from loading this Addon. To re-enable, delete the file."
)
if self.contains_workbench():
self.disable_workbench()
def enable(self):
"""Re-enable loading this addon by deleting the stopfile"""
@@ -601,6 +605,113 @@ class Addon:
except FileNotFoundError:
pass
if self.contains_workbench():
self.enable_workbench()
def enable_workbench(self):
wbName = self.get_workbench_name()
# Remove from the list of disabled.
self.remove_from_disabled_wbs(wbName)
def disable_workbench(self):
pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches")
wbName = self.get_workbench_name()
# Add the wb to the list of disabled if it was not already
disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench")
# print(f"start disabling {disabled_wbs}")
disabled_wbs_list = disabled_wbs.split(",")
if not (wbName in disabled_wbs_list):
disabled_wbs += "," + wbName
pref.SetString("Disabled", disabled_wbs)
# print(f"done disabling : {disabled_wbs} \n")
def desinstall_workbench(self):
pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches")
wbName = self.get_workbench_name()
# Remove from the list of ordered.
ordered_wbs = pref.GetString("Ordered", "")
# print(f"start remove from ordering {ordered_wbs}")
ordered_wbs_list = ordered_wbs.split(",")
ordered_wbs = ""
for wb in ordered_wbs_list:
if wb != wbName:
if ordered_wbs != "":
ordered_wbs += ","
ordered_wbs += wb
pref.SetString("Ordered", ordered_wbs)
# print(f"end remove from ordering {ordered_wbs}")
# Remove from the list of disabled.
self.remove_from_disabled_wbs(wbName)
def remove_from_disabled_wbs(self, wbName: str):
pref = fci.ParamGet("User parameter:BaseApp/Preferences/Workbenches")
disabled_wbs = pref.GetString("Disabled", "NoneWorkbench,TestWorkbench")
# print(f"start enabling : {disabled_wbs}")
disabled_wbs_list = disabled_wbs.split(",")
disabled_wbs = ""
for wb in disabled_wbs_list:
if wb != wbName:
if disabled_wbs != "":
disabled_wbs += ","
disabled_wbs += wb
pref.SetString("Disabled", disabled_wbs)
# print(f"Done enabling {disabled_wbs} \n")
def get_workbench_name(self) -> str:
"""Find the name of the workbench class (ie the name under which it's
registered in freecad core)'"""
wb_name = ""
if self.repo_type == Addon.Kind.PACKAGE:
for wb in self.metadata.content[
"workbench"
]: # we may have more than one wb.
if wb_name != "":
wb_name += ","
wb_name += wb.classname
if self.repo_type == Addon.Kind.WORKBENCH or wb_name == "":
wb_name = self.try_find_wbname_in_files()
if wb_name == "":
wb_name = self.name
return wb_name
def try_find_wbname_in_files(self) -> str:
"""Attempt to locate a line with an addWorkbench command in the workbench's
Python files. If it is directly instantiating a workbench, then we can use
the line to determine classname for this workbench. If it uses a variable,
or if the line doesn't exist at all, an empty string is returned."""
mod_dir = os.path.join(self.mod_directory, self.name)
for root, _, files in os.walk(mod_dir):
for f in files:
current_file = os.path.join(root, f)
if not os.path.isdir(current_file):
filename, extension = os.path.splitext(current_file)
if extension == ".py":
wb_classname = self._find_classname_in_file(current_file)
print(f"Current file: {current_file} ")
if wb_classname:
print(f"Found name {wb_classname} \n")
return wb_classname
return ""
@staticmethod
def _find_classname_in_file(current_file) -> str:
try:
with open(current_file, "r", encoding="utf-8") as python_file:
content = python_file.read()
search_result = re.search(r"Gui.addWorkbench\s*\(\s*(\w+)\s*\(\s*\)\s*\)", content)
if search_result:
return search_result.group(1)
except OSError:
pass
return ""
# @dataclass(frozen)
class MissingDependencies:

View File

@@ -20,7 +20,7 @@
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
import tempfile
import unittest
import os
import sys
@@ -32,14 +32,12 @@ from addonmanager_macro import Macro
class TestAddon(unittest.TestCase):
MODULE = "test_addon" # file name without extension
def setUp(self):
self.test_dir = os.path.join(os.path.dirname(__file__), "..", "data")
def test_display_name(self):
# Case 1: No display name set elsewhere: name == display_name
addon = Addon(
"FreeCAD",
@@ -82,7 +80,6 @@ class TestAddon(unittest.TestCase):
self.assertEqual(expected_tags, tags)
def test_contains_functions(self):
# Test package.xml combinations:
# Workbenches
@@ -200,7 +197,6 @@ class TestAddon(unittest.TestCase):
self.assertTrue(addon.__dict__, second_addon.__dict__)
def test_dependency_resolution(self):
addonA = Addon(
"AddonA",
"https://github.com/FreeCAD/FakeAddonA",
@@ -302,3 +298,114 @@ class TestAddon(unittest.TestCase):
"TagC" in addon.tags,
"Found 'TagA' in tags, it should have been excluded by version requirement",
)
def test_try_find_wbname_in_files_empty_dir(self):
with tempfile.TemporaryDirectory() as mod_dir:
# Arrange
test_addon = Addon("test")
test_addon.mod_directory = mod_dir
os.mkdir(os.path.join(mod_dir, test_addon.name))
# Act
wb_name = test_addon.try_find_wbname_in_files()
# Assert
self.assertEqual(wb_name, "")
def test_try_find_wbname_in_files_non_python_ignored(self):
with tempfile.TemporaryDirectory() as mod_dir:
# Arrange
test_addon = Addon("test")
test_addon.mod_directory = mod_dir
base_path = os.path.join(mod_dir, test_addon.name)
os.mkdir(base_path)
file_path = os.path.join(base_path, "test.txt")
with open(file_path, "w", encoding="utf-8") as f:
f.write("Gui.addWorkbench(TestWorkbench())")
# Act
wb_name = test_addon.try_find_wbname_in_files()
# Assert
self.assertEqual(wb_name, "")
def test_try_find_wbname_in_files_simple(self):
with tempfile.TemporaryDirectory() as mod_dir:
# Arrange
test_addon = Addon("test")
test_addon.mod_directory = mod_dir
base_path = os.path.join(mod_dir, test_addon.name)
os.mkdir(base_path)
file_path = os.path.join(base_path, "test.py")
with open(file_path, "w", encoding="utf-8") as f:
f.write("Gui.addWorkbench(TestWorkbench())")
# Act
wb_name = test_addon.try_find_wbname_in_files()
# Assert
self.assertEqual(wb_name, "TestWorkbench")
def test_try_find_wbname_in_files_subdir(self):
with tempfile.TemporaryDirectory() as mod_dir:
# Arrange
test_addon = Addon("test")
test_addon.mod_directory = mod_dir
base_path = os.path.join(mod_dir, test_addon.name)
os.mkdir(base_path)
subdir = os.path.join(base_path, "subdirectory")
os.mkdir(subdir)
file_path = os.path.join(subdir, "test.py")
with open(file_path, "w", encoding="utf-8") as f:
f.write("Gui.addWorkbench(TestWorkbench())")
# Act
wb_name = test_addon.try_find_wbname_in_files()
# Assert
self.assertEqual(wb_name, "TestWorkbench")
def test_try_find_wbname_in_files_variable_used(self):
with tempfile.TemporaryDirectory() as mod_dir:
# Arrange
test_addon = Addon("test")
test_addon.mod_directory = mod_dir
base_path = os.path.join(mod_dir, test_addon.name)
os.mkdir(base_path)
file_path = os.path.join(base_path, "test.py")
with open(file_path, "w", encoding="utf-8") as f:
f.write("Gui.addWorkbench(wb)")
# Act
wb_name = test_addon.try_find_wbname_in_files()
# Assert
self.assertEqual(wb_name, "")
def test_try_find_wbname_in_files_variants(self):
variants = [
"Gui.addWorkbench(TestWorkbench())",
"Gui.addWorkbench (TestWorkbench())",
"Gui.addWorkbench( TestWorkbench() )",
"Gui.addWorkbench(TestWorkbench( ))",
"Gui.addWorkbench( TestWorkbench( ) )",
"Gui.addWorkbench( TestWorkbench ( ) )",
"Gui.addWorkbench ( TestWorkbench ( ) )",
]
for variant in variants:
with self.subTest(variant=variant):
with tempfile.TemporaryDirectory() as mod_dir:
# Arrange
test_addon = Addon("test")
test_addon.mod_directory = mod_dir
base_path = os.path.join(mod_dir, test_addon.name)
os.mkdir(base_path)
file_path = os.path.join(base_path, "test.py")
with open(file_path, "w", encoding="utf-8") as f:
f.write(variant)
# Act
wb_name = test_addon.try_find_wbname_in_files()
# Assert
self.assertEqual(wb_name, "TestWorkbench")

View File

@@ -153,6 +153,11 @@ class AddonInstaller(QtCore.QObject):
success = self._install_by_git()
elif method_to_use == InstallationMethod.COPY:
success = self._install_by_copy()
if (
hasattr(self.addon_to_install, "contains_workbench")
and self.addon_to_install.contains_workbench()
):
self.addon_to_install.enable_workbench()
except utils.ProcessInterrupted:
pass
if success:

View File

@@ -113,6 +113,11 @@ class AddonUninstaller(QObject):
self.run_uninstall_script(path_to_remove)
self.remove_extra_files(path_to_remove)
success = utils.rmdir(path_to_remove)
if (
hasattr(self.addon_to_remove, "contains_workbench")
and self.addon_to_remove.contains_workbench()
):
self.addon_to_remove.desinstall_workbench()
except OSError as e:
error_message = str(e)
else: