Skip to content

Commit

Permalink
Addon Manager: Improve startup speed
Browse files Browse the repository at this point in the history
  • Loading branch information
chennes committed Jan 27, 2022
1 parent efaebbb commit f045a0b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 29 deletions.
4 changes: 3 additions & 1 deletion src/Mod/AddonManager/AddonManager.py
Expand Up @@ -42,7 +42,7 @@
from package_details import PackageDetails
from AddonManagerRepo import AddonManagerRepo

from NetworkManager import HAVE_QTNETWORK
from NetworkManager import HAVE_QTNETWORK, InitializeNetworkManager

__title__ = "FreeCAD Addon Manager Module"
__author__ = "Yorik van Havre", "Jonathan Wiedemann", "Kurt Kremitzki", "Chris Hennes"
Expand Down Expand Up @@ -131,6 +131,8 @@ def GetResources(self) -> Dict[str, str]:

def Activated(self) -> None:

InitializeNetworkManager()

# display first use dialog if needed
pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons")
readWarning = pref.GetBool("readWarning2022", False)
Expand Down
17 changes: 14 additions & 3 deletions src/Mod/AddonManager/NetworkManager.py
Expand Up @@ -146,6 +146,9 @@ def __init__(self):
self.synchronous_complete: Dict[int, bool] = {}
self.synchronous_result_data: Dict[int, QtCore.QByteArray] = {}

# Make sure we exit nicely on quit
QtCore.QCoreApplication.instance().aboutToQuit.connect(self.aboutToQuit)

def run(self):
"""Do not call directly: use start() to begin the event loop on a new thread."""

Expand Down Expand Up @@ -257,6 +260,10 @@ def run(self):
pass
QtCore.QCoreApplication.processEvents()

def aboutToQuit(self):
self.requestInterruption()


def submit_unmonitored_get(self, url: str) -> int:
"""Adds this request to the queue, and returns an index that can be used by calling code
in conjunction with the completed() signal to handle the results of the call. All data is
Expand Down Expand Up @@ -506,14 +513,18 @@ def abort(self, _):
pass # Nothing to do


AM_NETWORK_MANAGER = NetworkManager()
AM_NETWORK_MANAGER.start()

def InitializeNetworkManager():
global AM_NETWORK_MANAGER
if AM_NETWORK_MANAGER is None:
AM_NETWORK_MANAGER = NetworkManager()
AM_NETWORK_MANAGER.start()

if __name__ == "__main__":

app = QtCore.QCoreApplication()

InitializeNetworkManager()

count = 0

# For testing, create several network requests and send them off in quick succession:
Expand Down
6 changes: 3 additions & 3 deletions src/Mod/AddonManager/addonmanager_macro.py
Expand Up @@ -30,7 +30,7 @@
from typing import Dict, Tuple, List, Union

import FreeCAD
from NetworkManager import AM_NETWORK_MANAGER
import NetworkManager

translate = FreeCAD.Qt.translate

Expand Down Expand Up @@ -166,7 +166,7 @@ def fill_details_from_code(self, code: str) -> None:

def fill_details_from_wiki(self, url):
code = ""
p = AM_NETWORK_MANAGER.blocking_get(url)
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url)
if not p:
FreeCAD.Console.PrintWarning(
translate(
Expand All @@ -183,7 +183,7 @@ def fill_details_from_wiki(self, url):
rawcodeurl = re.findall('rawcodeurl.*?href="(http.*?)">', p)
if rawcodeurl:
rawcodeurl = rawcodeurl[0]
u2 = AM_NETWORK_MANAGER.blocking_get(rawcodeurl)
u2 = NetworkManager.AM_NETWORK_MANAGER.blocking_get(rawcodeurl)
if not u2:
FreeCAD.Console.PrintWarning(
translate(
Expand Down
44 changes: 22 additions & 22 deletions src/Mod/AddonManager/addonmanager_workers.py
Expand Up @@ -52,7 +52,7 @@
from addonmanager_macro import Macro

from AddonManagerRepo import AddonManagerRepo
from NetworkManager import AM_NETWORK_MANAGER
import NetworkManager

translate = FreeCAD.Qt.translate

Expand Down Expand Up @@ -119,7 +119,7 @@ def run(self):
translate("AddonsInstaller", "Checking network connection...\n")
)
url = "https://api.github.com/zen"
result = AM_NETWORK_MANAGER.blocking_get(url)
result = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url)
if QtCore.QThread.currentThread().isInterruptionRequested():
return
if not result:
Expand Down Expand Up @@ -153,7 +153,7 @@ def run(self):

# update info lists
global obsolete, macros_reject_list, mod_reject_list, py2only
p = AM_NETWORK_MANAGER.blocking_get(
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(
"https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/addonflags.json"
)
if p:
Expand Down Expand Up @@ -254,7 +254,7 @@ def run(self):
self.addon_repo.emit(repo)

# querying official addons
p = AM_NETWORK_MANAGER.blocking_get(
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(
"https://raw.githubusercontent.com/FreeCAD/FreeCAD-addons/master/.gitmodules"
)
if not p:
Expand Down Expand Up @@ -409,8 +409,8 @@ def check_workbench(self, wb):
"AddonManager: "
+ translate(
"AddonsInstaller",
f"Unable to fetch git updates for workbench {wb.name}",
)
"Unable to fetch git updates for workbench {}",
).format(wb.name)
)
else:
try:
Expand All @@ -425,7 +425,7 @@ def check_workbench(self, wb):
self.update_status.emit(wb)
except Exception:
FreeCAD.Console.PrintWarning(
translate("AddonsInstaller", "git fetch failed for {wb.name}")
translate("AddonsInstaller", "git fetch failed for {}").format(wb.name)
)

def check_package(self, package: AddonManagerRepo) -> None:
Expand Down Expand Up @@ -627,7 +627,7 @@ def retrieve_macros_from_wiki(self):
Reads only the page https://wiki.freecad.org/Macros_recipes
"""

p = AM_NETWORK_MANAGER.blocking_get("https://wiki.freecad.org/Macros_recipes")
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get("https://wiki.freecad.org/Macros_recipes")
if not p:
FreeCAD.Console.PrintWarning(
translate(
Expand Down Expand Up @@ -817,7 +817,7 @@ def run(self):
readmeurl = utils.get_readme_html_url(self.repo)
if not readmeurl:
FreeCAD.Console.PrintLog(f"README not found for {url}\n")
p = AM_NETWORK_MANAGER.blocking_get(readmeurl)
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(readmeurl)
if not p:
FreeCAD.Console.PrintLog(f"Debug: README not found at {readmeurl}\n")
p = p.data().decode("utf8")
Expand All @@ -831,7 +831,7 @@ def run(self):
readmeurl = utils.get_readme_url(self.repo)
if not readmeurl:
FreeCAD.Console.PrintLog(f"Debug: README not found for {url}\n")
p = AM_NETWORK_MANAGER.blocking_get(readmeurl)
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(readmeurl)
if p:
p = p.data().decode("utf8")
desc = utils.fix_relative_links(p, readmeurl.rsplit("/README.md")[0])
Expand All @@ -853,7 +853,7 @@ def run(self):
FreeCAD.Console.PrintLog("Debug: README not found at {readmeurl}\n")
if desc == "":
# fall back to the description text
p = AM_NETWORK_MANAGER.blocking_get(url)
p = NetworkManager.AM_NETWORK_MANAGER.blocking_get(url)
if not p:
return
p = p.data().decode("utf8")
Expand Down Expand Up @@ -942,7 +942,7 @@ def loadImages(self, message, url, wbName):
storename = os.path.join(store, wbName + name[-remainChars:])
if not os.path.exists(storename):
try:
imagedata = AM_NETWORK_MANAGER.blocking_get(path)
imagedata = NetworkManager.AM_NETWORK_MANAGER.blocking_get(path)
if not imagedata:
raise Exception
except Exception:
Expand Down Expand Up @@ -1225,9 +1225,9 @@ def launch_zip(self, zipdir: str) -> None:
self.zipdir = zipdir
self.bakdir = bakdir

AM_NETWORK_MANAGER.progress_made.connect(self.update_zip_status)
AM_NETWORK_MANAGER.progress_complete.connect(self.finish_zip)
self.zip_download_index = AM_NETWORK_MANAGER.submit_monitored_get(zipurl)
NetworkManager.AM_NETWORK_MANAGER.progress_made.connect(self.update_zip_status)
NetworkManager.AM_NETWORK_MANAGER.progress_complete.connect(self.finish_zip)
self.zip_download_index = NetworkManager.AM_NETWORK_MANAGER.submit_monitored_get(zipurl)

def update_zip_status(self, index: int, bytes_read: int, data_size: int):
if index == self.zip_download_index:
Expand Down Expand Up @@ -1492,7 +1492,7 @@ def __init__(self, repos):
self.requests: Dict[
int, (AddonManagerRepo, UpdateMetadataCacheWorker.RequestType)
] = {}
AM_NETWORK_MANAGER.completed.connect(self.download_completed)
NetworkManager.AM_NETWORK_MANAGER.completed.connect(self.download_completed)
self.requests_completed = 0
self.total_requests = 0
self.store = os.path.join(
Expand All @@ -1506,7 +1506,7 @@ def run(self):
for repo in self.repos:
if repo.url and utils.recognized_git_location(repo):
# package.xml
index = AM_NETWORK_MANAGER.submit_unmonitored_get(
index = NetworkManager.AM_NETWORK_MANAGER.submit_unmonitored_get(
utils.construct_git_url(repo, "package.xml")
)
self.requests[index] = (
Expand All @@ -1516,7 +1516,7 @@ def run(self):
self.total_requests += 1

# metadata.txt
index = AM_NETWORK_MANAGER.submit_unmonitored_get(
index = NetworkManager.AM_NETWORK_MANAGER.submit_unmonitored_get(
utils.construct_git_url(repo, "metadata.txt")
)
self.requests[index] = (
Expand All @@ -1526,7 +1526,7 @@ def run(self):
self.total_requests += 1

# requirements.txt
index = AM_NETWORK_MANAGER.submit_unmonitored_get(
index = NetworkManager.AM_NETWORK_MANAGER.submit_unmonitored_get(
utils.construct_git_url(repo, "requirements.txt")
)
self.requests[index] = (
Expand All @@ -1537,9 +1537,9 @@ def run(self):

while self.requests:
if current_thread.isInterruptionRequested():
AM_NETWORK_MANAGER.completed.disconnect(self.download_completed)
NetworkManager.AM_NETWORK_MANAGER.completed.disconnect(self.download_completed)
for request in self.requests.keys():
AM_NETWORK_MANAGER.abort(request)
NetworkManager.AM_NETWORK_MANAGER.abort(request)
return
# 50 ms maximum between checks for interruption
QtCore.QCoreApplication.processEvents(QtCore.QEventLoop.AllEvents, 50)
Expand Down Expand Up @@ -1603,7 +1603,7 @@ def process_package_xml(self, repo: AddonManagerRepo, data: QtCore.QByteArray):
icon = repo.Icon

icon_url = utils.construct_git_url(repo, icon)
index = AM_NETWORK_MANAGER.submit_unmonitored_get(icon_url)
index = NetworkManager.AM_NETWORK_MANAGER.submit_unmonitored_get(icon_url)
self.requests[index] = (repo, UpdateMetadataCacheWorker.RequestType.ICON)
self.total_requests += 1

Expand Down

0 comments on commit f045a0b

Please sign in to comment.