add proper pre-loading mechanism

Port language provider to new mechanism.
This commit is contained in:
Peter Eisenmann
2023-10-18 00:34:06 +02:00
parent 4e8e692503
commit dad3ffb7fc
5 changed files with 83 additions and 32 deletions

View File

@@ -16,6 +16,7 @@ from gi.repository import Adw, Gio, GLib, Gtk
# local, import order is important
from .global_state import global_state
from .preload_manager import preload_manager
from .window import OsInstallerWindow
APP_ID = 'com.github.p3732.OS-Installer'
@@ -42,6 +43,7 @@ class Application(Adw.Application):
global_state.set_config('version', version)
global_state.send_notification = self._send_notification
preload_manager.start()
def _setup_actions(self):
actions = [

View File

@@ -28,6 +28,7 @@ os_installer_sources = [
'provider/internet_provider.py',
'provider/keyboard_layout_provider.py',
'provider/language_provider.py',
'provider/preload_manager.py',
'provider/timezone_provider.py',
'ui/page.py',
'ui/pages/choices.py',
@@ -49,6 +50,7 @@ os_installer_sources = [
'ui/widgets.py',
'ui/window.py',
'util/installation_scripting.py',
'util/preloadable.py',
'util/system_calls.py',
'util/util.py',
]

View File

@@ -6,6 +6,7 @@ import os
from gi.repository import GObject, GnomeDesktop
from .global_state import global_state
from .preloadable import Preloadable
# generated via language_codes_to_x_generator.py
@@ -61,23 +62,9 @@ class LanguageInfo(GObject.GObject):
self.locale = locale
class LanguageProvider:
languages_loaded = False
languages_loading_lock = Lock()
def __init__(self, **kwargs):
# async load all languages from existing translations
localedir = global_state.get_config('localedir')
self.languages = global_state.thread_pool.submit(
self._get_languages, localedir=localedir)
def _assert_languages_loaded(self):
with self.languages_loading_lock:
if not self.languages_loaded:
self.all_languages, self.suggested, self.other = self.languages.result()
self.languages = None
self.languages_loaded = True
class LanguageProvider(Preloadable) :
def __init__(self):
Preloadable.__init__(self, self._get_languages)
def _get_default_locale(self, language):
if language in language_to_default_locale:
@@ -106,45 +93,44 @@ class LanguageProvider:
elif lang := GnomeDesktop.get_language_from_code(lang_code.split('_')[0], localization):
return f'{lang} ({lang_code})'
def _get_languages(self, localedir):
def _get_languages(self):
localedir = global_state.get_config('localedir')
translations = self._get_existing_translations(localedir)
all_languages = []
self.all_languages = []
unavailable_languages = []
for language_code in translations:
locale = self._get_default_locale(language_code)
if name := self._get_language_name_localized(locale, locale, language_code):
language_info = LanguageInfo(name, language_code, locale)
all_languages.append(language_info)
self.all_languages.append(language_info)
else:
unavailable_languages.append(language_code)
if unavailable_languages:
print('The following locales are not available on the current system: ',
sorted(unavailable_languages))
all_languages.sort(key=lambda k: k.name)
self.all_languages.sort(key=lambda k: k.name)
suggested = []
other = []
self.suggested = []
self.other = []
suggested_codes = global_state.get_config('suggested_languages')
if suggested_codes and len(suggested_codes) > 0:
for language_info in all_languages:
for language_info in self.all_languages:
if language_info.language_code in suggested_codes:
suggested.append(language_info)
self.suggested.append(language_info)
else:
other.append(language_info)
return (all_languages, suggested, other)
self.other.append(language_info)
### public methods ###
def get_all_languages(self):
self._assert_languages_loaded()
self.assert_preloaded()
return self.all_languages
def get_fixed_language(self, fixed_language):
self._assert_languages_loaded()
self.assert_preloaded()
fixed = [info for info in self.all_languages
if info.language_code == fixed_language]
@@ -157,11 +143,11 @@ class LanguageProvider:
return None
def get_suggested_languages(self):
self._assert_languages_loaded()
self.assert_preloaded()
return self.suggested
def get_other_languages(self):
self._assert_languages_loaded()
self.assert_preloaded()
return self.other
language_provider = LanguageProvider()

View File

@@ -0,0 +1,22 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from threading import Thread
from .language_provider import language_provider
class PreloadManager:
def __init__(self):
self.thread = Thread(target=self._preload)
def _preload(self):
language_provider.preload()
language_provider.assert_preloaded()
### public methods ###
def start(self):
self.thread.start()
preload_manager = PreloadManager()

39
src/util/preloadable.py Normal file
View File

@@ -0,0 +1,39 @@
# SPDX-License-Identifier: GPL-3.0-or-later
from threading import Lock
from .global_state import global_state
class Preloadable:
def __init__(self, preload_func):
self.preload_func = preload_func
self.preload_started = False
self.preloaded = False
self.preloading_lock = Lock()
### public methods ###
def assert_preloaded(self):
if self.preloaded:
return
with self.preloading_lock:
if self.preloaded:
return
if not self.preload_started:
print('Preloading for preloadable was never started')
self.preload()
# await result
self.future.result()
self.preloaded = True
def preload(self):
with self.preloading_lock:
if self.preload_started:
return
self.future = global_state.thread_pool.submit(self.preload_func)
self.preload_started = True