Core: Support disabling Addon by FreeCAD version
If package.xml metadata file exists, it is scanned for FreeCAD version compatibility before the Addon is loaded. If the Addon specifies that it is explicitly not compatible with the current version of FreeCAD, the Addon is not loaded.
This commit is contained in:
@@ -200,10 +200,16 @@ def InitApplications():
|
||||
MetadataFile = os.path.join(Dir, "package.xml")
|
||||
if os.path.exists(MetadataFile):
|
||||
meta = FreeCAD.Metadata(MetadataFile)
|
||||
if not meta.supportsCurrentFreeCAD():
|
||||
Msg(f'NOTICE: {meta.Name} does not support this version of FreeCAD, so is being skipped\n')
|
||||
continue
|
||||
content = meta.Content
|
||||
if "workbench" in content:
|
||||
workbenches = content["workbench"]
|
||||
for workbench in workbenches:
|
||||
if not workbench.supportsCurrentFreeCAD():
|
||||
Msg(f'NOTICE: {meta.Name} content item {workbench.Name} does not support this version of FreeCAD, so is being skipped\n')
|
||||
continue
|
||||
subdirectory = workbench.Name if not workbench.Subdirectory else workbench.Subdirectory
|
||||
subdirectory = subdirectory.replace("/",os.path.sep)
|
||||
subdirectory = os.path.join(Dir, subdirectory)
|
||||
@@ -226,12 +232,20 @@ def InitApplications():
|
||||
if freecad_module_ispkg:
|
||||
Log('Init: Initializing ' + freecad_module_name + '\n')
|
||||
try:
|
||||
|
||||
stopFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", freecad_module_name, "ADDON_DISABLED")
|
||||
# Check for a stopfile
|
||||
stopFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", freecad_module_name[8:], "ADDON_DISABLED")
|
||||
if os.path.exists(stopFile):
|
||||
Msg(f'NOTICE: Addon "{freecad_module_name}" disabled by presence of ADDON_DISABLED stopfile\n')
|
||||
continue
|
||||
|
||||
# Make sure that package.xml (if present) does not exclude this version of FreeCAD
|
||||
MetadataFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", freecad_module_name[8:], "package.xml")
|
||||
if os.path.exists(MetadataFile):
|
||||
meta = FreeCAD.Metadata(MetadataFile)
|
||||
if not meta.supportsCurrentFreeCAD():
|
||||
Msg(f'NOTICE: Addon "{freecad_module_name}" does not support this version of FreeCAD, so is being skipped\n')
|
||||
continue
|
||||
|
||||
freecad_module = importlib.import_module(freecad_module_name)
|
||||
extension_modules += [freecad_module_name]
|
||||
if any (module_name == 'init' for _, module_name, ispkg in pkgutil.iter_modules(freecad_module.__path__)):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2021 Chris Hennes <chennes@pioneerlibrarysystem.org> *
|
||||
* Copyright (c) 2022 FreeCAD Project Association *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -456,6 +456,23 @@ bool Metadata::satisfies(const Meta::Dependency& dep)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool App::Metadata::supportsCurrentFreeCAD() const
|
||||
{
|
||||
static auto fcVersion = Meta::Version();
|
||||
if (fcVersion == Meta::Version()) {
|
||||
std::map<std::string, std::string>& config = App::Application::Config();
|
||||
std::stringstream ss;
|
||||
ss << config["BuildVersionMajor"] << "." << config["BuildVersionMinor"] << "." << config["BuildRevision"].empty() ? "0" : config["BuildRevision"];
|
||||
fcVersion = Meta::Version(ss.str());
|
||||
}
|
||||
|
||||
if (_freecadmin != Meta::Version() && _freecadmin > fcVersion)
|
||||
return false;
|
||||
else if (_freecadmax != Meta::Version() && _freecadmax < fcVersion)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Metadata::appendToElement(DOMElement* root) const
|
||||
{
|
||||
appendSimpleXMLNode(root, "name", _name);
|
||||
|
||||
@@ -268,6 +268,12 @@ namespace App {
|
||||
*/
|
||||
bool satisfies(const Meta::Dependency&);
|
||||
|
||||
/**
|
||||
* Determine whether the current metadata specifies support for the currently-running version of FreeCAD.
|
||||
* Does not interrogate content items, which must be querried individually.
|
||||
*/
|
||||
bool supportsCurrentFreeCAD() const;
|
||||
|
||||
private:
|
||||
|
||||
std::string _name;
|
||||
|
||||
@@ -174,6 +174,16 @@ limited to 0.20 as the lowest known version since the metadata standard was adde
|
||||
</Documentation>
|
||||
</Methode>
|
||||
|
||||
<Methode Name="supportsCurrentFreeCAD">
|
||||
<Documentation>
|
||||
<UserDocu>supportsCurrentFreeCAD()
|
||||
Returns false if this metadata object directly indicates that it does not support the current
|
||||
version of FreeCAD, or true if it makes no indication, or specifically indicates that it does
|
||||
support the current version. Does not recurse into Content items.
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
|
||||
<Methode Name="getGenericMetadata">
|
||||
<Documentation>
|
||||
<UserDocu>getGenericMetadata(name)
|
||||
|
||||
@@ -318,8 +318,11 @@ void MetadataPy::setFreeCADMax(Py::Object args)
|
||||
getMetadataPtr()->setFreeCADMax(App::Meta::Version(version));
|
||||
}
|
||||
|
||||
PyObject* MetadataPy::getFirstSupportedFreeCADVersion(PyObject*)
|
||||
PyObject* MetadataPy::getFirstSupportedFreeCADVersion(PyObject* p)
|
||||
{
|
||||
if (!PyArg_ParseTuple(p, ""))
|
||||
return nullptr;
|
||||
|
||||
// Short-circuit: if the toplevel sets a version, then the lower-levels are overridden
|
||||
if (getMetadataPtr()->freecadmin() != App::Meta::Version())
|
||||
return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmin().str()));
|
||||
@@ -341,8 +344,11 @@ PyObject* MetadataPy::getFirstSupportedFreeCADVersion(PyObject*)
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* MetadataPy::getLastSupportedFreeCADVersion(PyObject*)
|
||||
PyObject* MetadataPy::getLastSupportedFreeCADVersion(PyObject* p)
|
||||
{
|
||||
if (!PyArg_ParseTuple(p, ""))
|
||||
return nullptr;
|
||||
|
||||
// Short-circuit: if the toplevel sets a version, then the lower-levels are overridden
|
||||
if (getMetadataPtr()->freecadmax() != App::Meta::Version())
|
||||
return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmax().str()));
|
||||
@@ -364,6 +370,15 @@ PyObject* MetadataPy::getLastSupportedFreeCADVersion(PyObject*)
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* MetadataPy::supportsCurrentFreeCAD(PyObject* p)
|
||||
{
|
||||
if (!PyArg_ParseTuple(p, ""))
|
||||
return nullptr;
|
||||
|
||||
bool result = getMetadataPtr()->supportsCurrentFreeCAD();
|
||||
return Py::new_reference_to(Py::Boolean(result));
|
||||
}
|
||||
|
||||
PyObject* MetadataPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -150,11 +150,15 @@ def InitApplications():
|
||||
MetadataFile = os.path.join(Dir, "package.xml")
|
||||
if os.path.exists(MetadataFile):
|
||||
meta = FreeCAD.Metadata(MetadataFile)
|
||||
if not meta.supportsCurrentFreeCAD():
|
||||
continue
|
||||
content = meta.Content
|
||||
if "workbench" in content:
|
||||
FreeCAD.Gui.addIconPath(Dir)
|
||||
workbenches = content["workbench"]
|
||||
for workbench_metadata in workbenches:
|
||||
if not workbench_metadata.supportsCurrentFreeCAD():
|
||||
continue
|
||||
subdirectory = workbench_metadata.Name if not workbench_metadata.Subdirectory else workbench_metadata.Subdirectory
|
||||
subdirectory = subdirectory.replace("/",os.path.sep)
|
||||
subdirectory = os.path.join(Dir, subdirectory)
|
||||
@@ -183,9 +187,18 @@ def InitApplications():
|
||||
import freecad
|
||||
freecad.gui = FreeCADGui
|
||||
for _, freecad_module_name, freecad_module_ispkg in pkgutil.iter_modules(freecad.__path__, "freecad."):
|
||||
stopFile = os.path.join(Dir, "ADDON_DISABLED")
|
||||
# Check for a stopfile
|
||||
stopFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", freecad_module_name[8:], "ADDON_DISABLED")
|
||||
if os.path.exists(stopFile):
|
||||
continue
|
||||
|
||||
# Make sure that package.xml (if present) does not exclude this version of FreeCAD
|
||||
MetadataFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", freecad_module_name[8:], "package.xml")
|
||||
if os.path.exists(MetadataFile):
|
||||
meta = FreeCAD.Metadata(MetadataFile)
|
||||
if not meta.supportsCurrentFreeCAD():
|
||||
continue
|
||||
|
||||
if freecad_module_ispkg:
|
||||
Log('Init: Initializing ' + freecad_module_name + '\n')
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user