Addon Manager: Bug fixes and license cleanup

This commit is contained in:
Chris Hennes
2024-02-10 11:48:29 -05:00
parent 43cb58f79e
commit 057bdda46b
8 changed files with 43 additions and 30 deletions

View File

@@ -223,12 +223,16 @@ class Addon:
@property
def license(self):
if not self._cached_license:
self._cached_license = "UNLICENSED"
if self.metadata and self.metadata.license:
self._cached_license = self.metadata.license
elif self.stats and self.stats.license:
self._cached_license = self.stats.license
elif self.macro and self.macro.license:
self._cached_license = self.macro.license
elif self.macro:
if self.macro.license:
self._cached_license = self.macro.license
elif self.macro.on_wiki:
self._cached_license = "CC-BY-3.0"
return self._cached_license
@classmethod

View File

@@ -550,8 +550,9 @@ class CommandAddonManager:
)
self.startup()
# Recaching implies checking for updates, regardless of the user's autocheck option
self.startup_sequence.remove(self.check_updates)
# Re-caching implies checking for updates, regardless of the user's autocheck option
if self.check_updates in self.startup_sequence:
self.startup_sequence.remove(self.check_updates)
self.startup_sequence.append(self.force_check_updates)
def on_package_updated(self, repo: Addon) -> None:

View File

@@ -391,7 +391,8 @@ if HAVE_QTNETWORK:
def __synchronous_process_completion(
self, index: int, code: int, data: QtCore.QByteArray
) -> None:
"""Check the return status of a completed process, and handle its returned data (if any)."""
"""Check the return status of a completed process, and handle its returned data (if
any)."""
with self.synchronous_lock:
if index in self.synchronous_complete:
if code == 200:
@@ -406,7 +407,8 @@ if HAVE_QTNETWORK:
)
self.synchronous_complete[index] = True
def __create_get_request(self, url: str, timeout_ms: int) -> QtNetwork.QNetworkRequest:
@staticmethod
def __create_get_request(url: str, timeout_ms: int) -> QtNetwork.QNetworkRequest:
"""Construct a network request to a given URL"""
request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
request.setAttribute(
@@ -560,21 +562,20 @@ if HAVE_QTNETWORK:
# This can happen during a cancellation operation: silently do nothing
return
if reply.error() == QtNetwork.QNetworkReply.NetworkError.OperationCanceledError:
# Silently do nothing
return
index = None
for key, value in self.replies.items():
if reply == value:
index = key
break
if index is None:
print(f"Lost net request for {reply.url()}")
return
response_code = reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute)
self.queue.task_done()
if response_code == 301: # Permanently moved -- this is a redirect, bail out
return
if reply.error() != QtNetwork.QNetworkReply.NetworkError.OperationCanceledError:
# It this was not a timeout, make sure we mark the queue task done
self.queue.task_done()
if reply.error() == QtNetwork.QNetworkReply.NetworkError.NoError:
if index in self.monitored_connections:
# Make sure to read any remaining data

View File

@@ -75,6 +75,8 @@ class SPDXLicenseManager:
def is_osi_approved(self, spdx_id: str) -> bool:
"""Check to see if the license is OSI-approved, according to the SPDX database. Returns
False if the license is not in the database, or is not marked as "isOsiApproved"."""
if spdx_id == "UNLICENSED" or spdx_id == "UNLICENCED" or spdx_id.startswith("SEE LIC"):
return False
if spdx_id not in self.license_data:
fci.Console.PrintWarning(
f"WARNING: License ID {spdx_id} is not in the SPDX license "
@@ -89,6 +91,8 @@ class SPDXLicenseManager:
def is_fsf_libre(self, spdx_id: str) -> bool:
"""Check to see if the license is FSF Free/Libre, according to the SPDX database. Returns
False if the license is not in the database, or is not marked as "isFsfLibre"."""
if spdx_id == "UNLICENSED" or spdx_id == "UNLICENCED" or spdx_id.startswith("SEE LIC"):
return False
if spdx_id not in self.license_data:
fci.Console.PrintWarning(
f"WARNING: License ID {spdx_id} is not in the SPDX license "
@@ -100,6 +104,10 @@ class SPDXLicenseManager:
)
def name(self, spdx_id: str) -> str:
if spdx_id == "UNLICENSED":
return "All rights reserved"
if spdx_id.startswith("SEE LIC"): # "SEE LICENSE IN" or "SEE LICENCE IN"
return f"Custom license: {spdx_id}"
if spdx_id not in self.license_data:
return ""
return self.license_data[spdx_id]["name"]
@@ -145,21 +153,24 @@ class SPDXLicenseManager:
.replace("GPL2", "GPL-2")
.replace("GPL3", "GPL-3")
)
if self.name(normed):
or_later = ""
if normed.endswith("+"):
normed = normed[:-1]
or_later = "-or-later"
if self.name(normed + or_later):
fci.Console.PrintLog(f"found valid SPDX license ID {normed}\n")
return normed
return normed + or_later
# If it still doesn't match, try some other things
while "--" in normed:
normed = license_string.replace("--", "-")
normed = normed.replace("--", "-")
if self.name(normed):
if self.name(normed + or_later):
fci.Console.PrintLog(f"found valid SPDX license ID {normed}\n")
return normed
if not normed.endswith(".0"):
normed += ".0"
if self.name(normed):
return normed + or_later
normed += ".0"
if self.name(normed + or_later):
fci.Console.PrintLog(f"found valid SPDX license ID {normed}\n")
return normed
return normed + or_later
fci.Console.PrintLog(f"failed to normalize (typo in ID or invalid version number??)\n")
return license_string # We failed to normalize this one

View File

@@ -160,9 +160,6 @@ class Macro:
code = self._fetch_raw_code(p)
if not code:
code = self._read_code_from_wiki(p)
if not self.license:
# The default license on the wiki is CC-BY-3.0 (which is non-Libre and not OSI-approved)
self.license = "CC-BY-3.0"
if not code:
self._console.PrintWarning(
translate("AddonsInstaller", "Unable to fetch the code of this macro.") + "\n"

View File

@@ -380,7 +380,7 @@ def blocking_get(url: str, method=None) -> bytes:
p = b""
if fci.FreeCADGui and method is None or method == "networkmanager":
NetworkManager.InitializeNetworkManager()
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url)
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url, 10000) # 10 second timeout
if p:
try:
p = p.data()

View File

@@ -87,7 +87,7 @@ class UpdateMetadataCacheWorker(QtCore.QThread):
current_thread = QtCore.QThread.currentThread()
for repo in self.repos:
if repo.url and utils.recognized_git_location(repo):
if not repo.macro and repo.url and utils.recognized_git_location(repo):
# package.xml
index = NetworkManager.AM_NETWORK_MANAGER.submit_unmonitored_get(
utils.construct_git_url(repo, "package.xml")
@@ -120,7 +120,6 @@ class UpdateMetadataCacheWorker(QtCore.QThread):
while self.requests:
if current_thread.isInterruptionRequested():
NetworkManager.AM_NETWORK_MANAGER.completed.disconnect(self.download_completed)
for request in self.requests:
NetworkManager.AM_NETWORK_MANAGER.abort(request)
return

View File

@@ -93,7 +93,7 @@ class CreateAddonListWorker(QtCore.QThread):
def _get_freecad_addon_repo_data(self):
# update info lists
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(
"https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/addonflags.json"
"https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/addonflags.json", 5000
)
if p:
p = p.data().decode("utf8")
@@ -203,7 +203,7 @@ class CreateAddonListWorker(QtCore.QThread):
def _get_official_addons(self):
# querying official addons
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(
"https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/.gitmodules"
"https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/.gitmodules", 5000
)
if not p:
return
@@ -369,7 +369,7 @@ class CreateAddonListWorker(QtCore.QThread):
"""
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(
"https://wiki.freecad.org/Macros_recipes"
"https://wiki.freecad.org/Macros_recipes", 5000
)
if not p:
# The Qt Python translation extractor doesn't support splitting this string (yet)