diff --git a/qubes_config/global_config/global_config.py b/qubes_config/global_config/global_config.py index c1ca2fa7..e0b8b3f6 100644 --- a/qubes_config/global_config/global_config.py +++ b/qubes_config/global_config/global_config.py @@ -23,7 +23,7 @@ import sys from typing import Dict, Optional, List, Union from html import escape -import pkg_resources +import importlib.resources import logging import qubesadmin @@ -252,18 +252,19 @@ def perform_setup(self): self.progress_bar_dialog.update_progress(0) self.builder = Gtk.Builder() - self.builder.add_from_file(pkg_resources.resource_filename( - 'qubes_config', 'global_config.glade')) + glade_ref = (importlib.resources.files('qubes_config') / + 'global_config.glade') + with importlib.resources.as_file(glade_ref) as path: + self.builder.add_from_file(str(path)) self.main_window: Gtk.Window = self.builder.get_object('main_window') self.main_notebook: Gtk.Notebook = \ self.builder.get_object('main_notebook') load_theme(widget=self.main_window, - light_theme_path=pkg_resources.resource_filename( - 'qubes_config', 'qubes-global-config-light.css'), - dark_theme_path=pkg_resources.resource_filename( - 'qubes_config', 'qubes-global-config-dark.css')) + package_name='qubes_config', + light_file_name='qubes-global-config-light.css', + dark_file_name='qubes-global-config-dark.css') self.apply_button: Gtk.Button = self.builder.get_object('apply_button') self.cancel_button: Gtk.Button = \ diff --git a/qubes_config/new_qube/new_qube_app.py b/qubes_config/new_qube/new_qube_app.py index a06f2d5f..52ca6687 100644 --- a/qubes_config/new_qube/new_qube_app.py +++ b/qubes_config/new_qube/new_qube_app.py @@ -24,7 +24,7 @@ import subprocess import sys from typing import Optional, Dict, Any -import pkg_resources +import importlib.resources import logging import qubesadmin @@ -93,8 +93,10 @@ def perform_setup(self): self.progress_bar_dialog.update_progress(0.1) self.builder = Gtk.Builder() - self.builder.add_from_file(pkg_resources.resource_filename( - 'qubes_config', 'new_qube.glade')) + glade_ref = (importlib.resources.files('qubes_config') / + 'new_qube.glade') + with importlib.resources.as_file(glade_ref) as path: + self.builder.add_from_file(str(path)) self.main_window = self.builder.get_object('main_window') self.qube_name: Gtk.Entry = self.builder.get_object('qube_name') @@ -102,10 +104,9 @@ def perform_setup(self): self.builder.get_object('qube_label') load_theme(widget=self.main_window, - light_theme_path=pkg_resources.resource_filename( - 'qubes_config', 'qubes-new-qube-light.css'), - dark_theme_path=pkg_resources.resource_filename( - 'qubes_config', 'qubes-new-qube-dark.css')) + package_name='qubes_config', + light_file_name='qubes-new-qube-light.css', + dark_file_name='qubes-new-qube-dark.css') self.progress_bar_dialog.update_progress(0.1) diff --git a/qubes_config/policy_editor/policy_editor.py b/qubes_config/policy_editor/policy_editor.py index 7735f374..f8f531ac 100644 --- a/qubes_config/policy_editor/policy_editor.py +++ b/qubes_config/policy_editor/policy_editor.py @@ -24,7 +24,7 @@ from typing import Callable, Optional, Dict, Tuple import gi -import pkg_resources +import importlib.resources import qubesadmin from qrexec.policy.admin_client import PolicyClient @@ -171,8 +171,11 @@ def perform_setup(self): Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) self.builder = Gtk.Builder() - self.builder.add_from_file(pkg_resources.resource_filename( - 'qubes_config', 'policy_editor.glade')) + + glade_ref = (importlib.resources.files('qubes_config') / + 'policy_editor.glade') + with importlib.resources.as_file(glade_ref) as path: + self.builder.add_from_file(str(path)) self.file_select_handler = OpenDialogHandler(self.builder, self.policy_client, @@ -218,16 +221,14 @@ def perform_setup(self): self.setup_actions() self.setup_menu() - load_theme(widget=self.main_window, - light_theme_path=pkg_resources.resource_filename( - 'qubes_config', 'qubes-policy-editor-light.css'), - dark_theme_path=pkg_resources.resource_filename( - 'qubes_config', 'qubes-policy-editor-dark.css')) + load_theme(widget=self.main_window, package_name='qubes_config', + light_file_name='qubes-policy-editor-light.css', + dark_file_name='qubes-policy-editor-dark.css') self.setup_source() - - help_text = pkg_resources.resource_string( - 'qubes_config', 'policy_editor/policy_help.txt').decode() + help_text = importlib.resources.files( + 'qubes_config').joinpath( + 'policy_editor/policy_help.txt').read_text() self.builder.get_object("help_label").set_markup(help_text) self.open_policy_file(self.filename) diff --git a/qubes_config/tests/conftest.py b/qubes_config/tests/conftest.py index 8bfbe9c2..47a51afb 100644 --- a/qubes_config/tests/conftest.py +++ b/qubes_config/tests/conftest.py @@ -20,7 +20,7 @@ """Conftest helper pytest file: fixtures container here are reachable by all tests""" import pytest -import pkg_resources +import importlib.resources import subprocess from typing import Mapping, Union, Tuple, List from qubesadmin.tests import QubesTest @@ -436,8 +436,10 @@ def test_builder(): SIGNALS_REGISTERED = True # test glade file contains very simple setup with correctly named widgets builder = Gtk.Builder() - builder.add_from_file(pkg_resources.resource_filename( - __name__, 'test.glade')) + glade_ref = (importlib.resources.files('qubes_config') / + 'tests/test.glade') + with importlib.resources.as_file(glade_ref) as path: + builder.add_from_file(str(path)) return builder @pytest.fixture @@ -450,8 +452,10 @@ def real_builder(): SIGNALS_REGISTERED = True # test glade file contains very simple setup with correctly named widgets builder = Gtk.Builder() - builder.add_from_file(pkg_resources.resource_filename( - 'qubes_config', 'global_config.glade')) + glade_ref = (importlib.resources.files('qubes_config') / + 'global_config.glade') + with importlib.resources.as_file(glade_ref) as path: + builder.add_from_file(str(path)) return builder @@ -468,8 +472,10 @@ def new_qube_builder(): NEW_QUBE_SIGNALS_REGISTERED = True # test glade file contains very simple setup with correctly named widgets builder = Gtk.Builder() - builder.add_from_file(pkg_resources.resource_filename( - 'qubes_config', 'new_qube.glade')) + glade_ref = (importlib.resources.files('qubes_config') / + 'new_qube.glade') + with importlib.resources.as_file(glade_ref) as path: + builder.add_from_file(str(path)) return builder diff --git a/qubes_config/widgets/gtk_utils.py b/qubes_config/widgets/gtk_utils.py index 978fd2e7..09bf865b 100644 --- a/qubes_config/widgets/gtk_utils.py +++ b/qubes_config/widgets/gtk_utils.py @@ -19,6 +19,7 @@ # with this program; if not, see . """Utility functions using Gtk""" import contextlib +import importlib.resources import os import fcntl @@ -187,14 +188,31 @@ def show_dialog( return dialog -def load_theme(widget: Gtk.Widget, light_theme_path: str, dark_theme_path: str): +def load_theme(widget: Gtk.Widget, light_theme_path: Optional[str] = None, + dark_theme_path: Optional[str] = None, + package_name: Optional[str] = None, + light_file_name: Optional[str] = None, + dark_file_name: Optional[str] = None): """ Load a dark or light theme to current screen, based on widget's current (system) defaults. :param widget: Gtk.Widget, preferably main window :param light_theme_path: path to file with light theme css :param dark_theme_path: path to file with dark theme css + Alternatively, you can provide: + :param package_name: name of the package + :param light_file_name: name of the css file with light theme + :param dark_file_name: name of the css file with dark theme """ + if not light_theme_path and light_file_name: + css_path = importlib.resources.files(package_name) / light_file_name + with importlib.resources.as_file(css_path) as resource_path: + light_theme_path = str(resource_path) + if not dark_theme_path and dark_file_name: + css_path = importlib.resources.files(package_name) / dark_file_name + with importlib.resources.as_file(css_path) as resource_path: + dark_theme_path = str(resource_path) + path = light_theme_path if is_theme_light(widget) else dark_theme_path screen = Gdk.Screen.get_default() diff --git a/qui/devices/device_widget.py b/qui/devices/device_widget.py index d7615a92..4fcc66f9 100644 --- a/qui/devices/device_widget.py +++ b/qui/devices/device_widget.py @@ -21,7 +21,7 @@ import asyncio import sys -import pkg_resources +import importlib.resources import qubesadmin import qubesadmin.exc @@ -281,8 +281,11 @@ def load_css(widget) -> str: theme = 'light' if is_theme_light(widget) else 'dark' screen = Gdk.Screen.get_default() provider = Gtk.CssProvider() - provider.load_from_path(pkg_resources.resource_filename( - 'qui', f'qubes-devices-{theme}.css')) + css_file_ref = (importlib.resources.files('qui') / + f'qubes-devices-{theme}.css') + with importlib.resources.as_file(css_file_ref) as css_file: + provider.load_from_path(str(css_file)) + Gtk.StyleContext.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) diff --git a/qui/updater/tests/conftest.py b/qui/updater/tests/conftest.py index 56db38a8..396fa88b 100644 --- a/qui/updater/tests/conftest.py +++ b/qui/updater/tests/conftest.py @@ -20,7 +20,7 @@ """Conftest helper pytest file: fixtures container here are reachable by all tests""" import pytest -import pkg_resources +import importlib.resources from qubes_config.tests.conftest import add_dom0_vm_property, \ add_dom0_text_property, add_dom0_feature, add_expected_vm, \ @@ -141,8 +141,10 @@ def real_builder(): """Gtk builder with actual config glade file registered""" builder = Gtk.Builder() builder.set_translation_domain("desktop-linux-manager") - builder.add_from_file(pkg_resources.resource_filename( - 'qui', 'updater.glade')) + glade_ref = (importlib.resources.files('qui') / + 'updater.glade') + with importlib.resources.as_file(glade_ref) as path: + self.builder.add_from_file(str(path)) return builder diff --git a/qui/updater/updater.py b/qui/updater/updater.py index fbeb596c..fac1bded 100644 --- a/qui/updater/updater.py +++ b/qui/updater/updater.py @@ -5,7 +5,7 @@ import logging import time -import pkg_resources +import importlib.resources import gi # isort:skip from qubes_config.widgets.gtk_utils import load_icon_at_gtk_size, load_theme, \ @@ -78,8 +78,11 @@ def perform_setup(self, *_args, **_kwargs): # pylint: disable=attribute-defined-outside-init self.builder = Gtk.Builder() self.builder.set_translation_domain("desktop-linux-manager") - self.builder.add_from_file(pkg_resources.resource_filename( - 'qui', 'updater.glade')) + + glade_ref = (importlib.resources.files('qui') / + 'updater.glade') + with importlib.resources.as_file(glade_ref) as path: + self.builder.add_from_file(str(path)) self.main_window: Gtk.Window = self.builder.get_object("main_window") self.next_button: Gtk.Button = self.builder.get_object("button_next") @@ -89,10 +92,9 @@ def perform_setup(self, *_args, **_kwargs): self.cancel_button.connect("clicked", self.cancel_clicked) load_theme(widget=self.main_window, - light_theme_path=pkg_resources.resource_filename( - 'qui', 'qubes-updater-light.css'), - dark_theme_path=pkg_resources.resource_filename( - 'qui', 'qubes-updater-dark.css')) + package_name='qui', + light_file_name='qubes-updater-light.css', + dark_file_name='qubes-updater-dark.css') self.header_label: Gtk.Label = self.builder.get_object("header_label") diff --git a/qui/updater/updater_settings.py b/qui/updater/updater_settings.py index a463fc7b..4b5d45f4 100644 --- a/qui/updater/updater_settings.py +++ b/qui/updater/updater_settings.py @@ -21,7 +21,7 @@ import dataclasses from typing import Optional, Union, Callable -import pkg_resources +import importlib.resources import gi gi.require_version('Gtk', '3.0') # isort:skip @@ -68,8 +68,11 @@ def __init__( self.builder = Gtk.Builder() self.builder.set_translation_domain("desktop-linux-manager") - self.builder.add_from_file(pkg_resources.resource_filename( - 'qui', 'updater_settings.glade')) + + glade_ref = (importlib.resources.files('qui') / + 'updater_settings.glade') + with importlib.resources.as_file(glade_ref) as path: + self.builder.add_from_file(str(path)) self.settings_window: Gtk.Window = self.builder.get_object( "main_window") diff --git a/qui/utils.py b/qui/utils.py index 4b917e4a..4835924d 100644 --- a/qui/utils.py +++ b/qui/utils.py @@ -27,7 +27,7 @@ import gettext -import pkg_resources +import importlib.resources from datetime import datetime t = gettext.translation("desktop-linux-manager", fallback=True) @@ -37,7 +37,8 @@ gi.require_version('Gtk', '3.0') # isort:skip from gi.repository import Gtk # isort:skip -EOL_DATES = json.load(pkg_resources.resource_stream(__name__, 'eol.json')) +with importlib.resources.files('qui').joinpath('eol.json').open() as stream: + EOL_DATES = json.load(stream) # remove the following suffixes when checking for EOL SUFFIXES = ['-minimal', '-xfce']