diff --git a/mypy.ini b/mypy.ini index 7160dbf6..93af0712 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,5 +1,6 @@ [mypy] files = qubes_config +exclude = qubes_config/tests/* ignore_missing_imports = True check_untyped_defs = True diff --git a/qubes_config/global_config/basics_handler.py b/qubes_config/global_config/basics_handler.py index e1f1974e..2e6536ce 100644 --- a/qubes_config/global_config/basics_handler.py +++ b/qubes_config/global_config/basics_handler.py @@ -134,7 +134,7 @@ def __init__( widget: Gtk.ComboBox, vm_filter: Optional[Callable] = None, readable_name: Optional[str] = None, - additional_options: Optional[Dict[str, str]] = None, + additional_options: Dict[Any | str | None, str] | None = None, ): self.qapp = qapp self.trait_holder = trait_holder diff --git a/qubes_config/global_config/rule_list_widgets.py b/qubes_config/global_config/rule_list_widgets.py index 6d62669a..04ee3de6 100644 --- a/qubes_config/global_config/rule_list_widgets.py +++ b/qubes_config/global_config/rule_list_widgets.py @@ -18,7 +18,7 @@ # You should have received a copy of the GNU Lesser General Public License along # with this program; if not, see . """Widgets used by various list of policy rules.""" -from typing import Optional, Dict, Callable +from typing import Optional, Dict, Callable, Any from ..widgets.gtk_widgets import ( VMListModeler, @@ -43,14 +43,14 @@ t = gettext.translation("desktop-linux-manager", fallback=True) _ = t.gettext -SOURCE_CATEGORIES = { +SOURCE_CATEGORIES: dict[Any | str | None, str] | None = { "@anyvm": _("ALL QUBES"), "@type:AppVM": _("TYPE: APP"), "@type:TemplateVM": _("TYPE: TEMPLATES"), "@type:DispVM": _("TYPE: DISPOSABLE"), } -SOURCE_CATEGORIES_ADMIN = { +SOURCE_CATEGORIES_ADMIN: dict[Any | str | None, str] | None = { "@anyvm": _("ALL QUBES"), "@type:AppVM": _("TYPE: APP"), "@type:TemplateVM": _("TYPE: TEMPLATES"), @@ -58,7 +58,7 @@ "@adminvm": _("TYPE: ADMINVM"), } -TARGET_CATEGORIES = { +TARGET_CATEGORIES: dict[Any | str | None, str] | None = { "@anyvm": _("ALL QUBES"), "@dispvm": _("Default Disposable Qube"), "@type:AppVM": _("TYPE: APP"), @@ -66,13 +66,13 @@ "@type:DispVM": _("TYPE: DISPOSABLE"), } -LIMITED_CATEGORIES = { +LIMITED_CATEGORIES: dict[Any | str | None, str] | None = { "@type:AppVM": _("TYPE: APP"), "@type:TemplateVM": _("TYPE: TEMPLATES"), "@type:DispVM": _("TYPE: DISPOSABLE"), } -DISPVM_CATEGORIES = { +DISPVM_CATEGORIES: dict[Any | str | None, str] | None = { "@dispvm": _("Default Disposable Template"), } @@ -83,12 +83,12 @@ class VMWidget(Gtk.Box): def __init__( self, qapp: qubesadmin.Qubes, - categories: Optional[Dict[str, str]], + categories: Dict[Any | str | None, str] | None, initial_value: str, additional_text: Optional[str] = None, - additional_widget: Optional[Gtk.Widget] = None, - filter_function: Optional[Callable[[qubesadmin.vm.QubesVM], bool]] = None, - change_callback: Optional[Callable] = None, + additional_widget: Gtk.Widget | None = None, + filter_function: Callable[[qubesadmin.vm.QubesVM], bool] | None = None, + change_callback: Callable | None = None, ): """ :param qapp: Qubes object diff --git a/qubes_config/global_config/updates_handler.py b/qubes_config/global_config/updates_handler.py index 04158df9..704eccea 100644 --- a/qubes_config/global_config/updates_handler.py +++ b/qubes_config/global_config/updates_handler.py @@ -491,13 +491,18 @@ def load_rules(self): for rule in reversed(self.rules): if rule.source == "@type:TemplateVM": - def_updatevm = rule.action.target + if rule.action == "deny": + def_updatevm = None + else: + def_updatevm = rule.action.target elif rule.source == "@tag:whonix-updatevm": - def_whonix_updatevm = rule.action.target + if rule.action == "deny": + def_whonix_updatevm = None + else: + def_whonix_updatevm = rule.action.target - if def_updatevm: - self.updatevm_model.select_value(str(def_updatevm)) - self.updatevm_model.update_initial() + self.updatevm_model.select_value(str(def_updatevm)) + self.updatevm_model.update_initial() if self.has_whonix: self.whonix_updatevm_model.select_value(str(def_whonix_updatevm)) @@ -589,27 +594,41 @@ def save(self): new_update_proxies.add(self.qapp.domains[rule.target]) if self.has_whonix: - raw_rules.append( - self.policy_manager.new_rule( + if self.whonix_updatevm_model.get_selected(): + rule = self.policy_manager.new_rule( service=self.service_name, source="@tag:whonix-updatevm", target="@default", action="allow " f"target={self.whonix_updatevm_model.get_selected()}", ) - ) - new_update_proxies.add(self.whonix_updatevm_model.get_selected()) - - if self.updatevm_model.get_selected(): - raw_rules.append( - self.policy_manager.new_rule( + else: + rule = self.policy_manager.new_rule( service=self.service_name, - source="@type:TemplateVM", + source="@tag:whonix-updatevm", target="@default", - action="allow " f"target={self.updatevm_model.get_selected()}", + action="deny", ) + raw_rules.append(rule) + new_update_proxies.add(self.whonix_updatevm_model.get_selected()) + + # always have a rule for updatevm + if self.updatevm_model.get_selected(): + rule = self.policy_manager.new_rule( + service=self.service_name, + source="@type:TemplateVM", + target="@default", + action=f"allow target={self.updatevm_model.get_selected()}", ) new_update_proxies.add(self.updatevm_model.get_selected()) + else: + rule = self.policy_manager.new_rule( + service=self.service_name, + source="@type:TemplateVM", + target="@default", + action="deny", + ) + raw_rules.append(rule) self.policy_manager.save_rules( self.policy_file_name, raw_rules, self.current_token diff --git a/qubes_config/widgets/gtk_widgets.py b/qubes_config/widgets/gtk_widgets.py index 9f7d8719..415b7144 100644 --- a/qubes_config/widgets/gtk_widgets.py +++ b/qubes_config/widgets/gtk_widgets.py @@ -29,7 +29,7 @@ gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GdkPixbuf -from typing import Optional, Callable, Dict, Any, Union, List +from typing import Callable, Any from .gtk_utils import load_icon, is_theme_light @@ -38,7 +38,7 @@ t = gettext.translation("desktop-linux-manager", fallback=True) _ = t.gettext -NONE_CATEGORY = {"None": _("(none)")} +NONE_CATEGORY: dict[Any | str | None, str] = {"None": _("(none)")} class TokenName(Gtk.Box): @@ -50,12 +50,12 @@ def __init__( self, token_name: str, qapp: qubesadmin.Qubes, - categories: Optional[Dict[str, str]] = None, + categories: dict[Any | str | None, str] | None = None, ): """ :param token_name: string for of the token :param qapp: Qubes object - :param categories: dict of human-readable names for token strings + :param categories: dict of human-readable names for tokens """ super().__init__(orientation=Gtk.Orientation.HORIZONTAL) self.qapp = qapp @@ -88,7 +88,7 @@ class QubeName(Gtk.Box): bolded. """ - def __init__(self, vm: Optional[qubesadmin.vm.QubesVM]): + def __init__(self, vm: qubesadmin.vm.QubesVM | None): """ :param vm: Qubes VM to be represented. """ @@ -151,8 +151,8 @@ class TextModeler(TraitSelector): def __init__( self, combobox: Gtk.ComboBoxText, - values: Dict[str, Any], - selected_value: Optional[Any] = None, + values: dict[str, Any], + selected_value: Any = None, style_changes: bool = False, ): """ @@ -166,7 +166,7 @@ def __init__( applied when combobox value is different from initial value. """ self._combo: Gtk.ComboBoxText = combobox - self._values: Dict[str, Any] = values + self._values: dict[str, Any] = values if selected_value and selected_value not in self._values.values(): self._values[selected_value] = selected_value @@ -228,12 +228,12 @@ def __init__( self, combobox: Gtk.ComboBox, qapp: qubesadmin.Qubes, - filter_function: Optional[Callable[[qubesadmin.vm.QubesVM], bool]] = None, - event_callback: Optional[Callable[[], None]] = None, - default_value: Optional[Union[qubesadmin.vm.QubesVM, str]] = None, - current_value: Optional[Union[qubesadmin.vm.QubesVM, str]] = None, + filter_function: Callable[[qubesadmin.vm.QubesVM], bool] | None = None, + event_callback: Callable[[], None] | None = None, + default_value: qubesadmin.vm.QubesVM | str | None = None, + current_value: qubesadmin.vm.QubesVM | str | None = None, style_changes: bool = False, - additional_options: Optional[Dict[str, str]] = None, + additional_options: dict[qubesadmin.vm.QubesVM | str | None, str] | None = None, ): """ :param combobox: target ComboBox object @@ -253,7 +253,7 @@ def __init__( :param style_changes: if True, combo-changed style class will be applied when combobox value changes :param additional_options: Dictionary of token: readable name of - addiitonal options to be added to the combobox + additonal options to be added to the combobox """ self.qapp = qapp self.combo = combobox @@ -261,9 +261,9 @@ def __init__( self.change_function = event_callback self.style_changes = style_changes - self._entries: Dict[str, Dict[str, Any]] = {} + self._entries: dict[str, dict[str, Any]] = {} - self._icons: Dict[str, Gtk.Image] = {} + self._icons: dict[str, Gtk.Image] = {} self._icon_size = 20 self._create_entries( @@ -321,10 +321,10 @@ def _get_icon(self, name): def _create_entries( self, - filter_function: Optional[Callable[[qubesadmin.vm.QubesVM], bool]], - default_value: Optional[Union[qubesadmin.vm.QubesVM, str]], - additional_options: Optional[Dict[str, str]] = None, - current_value: Optional[str] = None, + filter_function: Callable[[qubesadmin.vm.QubesVM], bool] | None, + default_value: qubesadmin.vm.QubesVM | str | None, + additional_options: dict[qubesadmin.vm.QubesVM | str | None, str] | None = None, + current_value: str | None = None, ): if additional_options: @@ -458,7 +458,7 @@ def _event_callback(self, *_args): def __str__(self): return self.entry_box.get_text() - def get_selected(self) -> Optional[qubesadmin.vm.QubesVM]: + def get_selected(self) -> qubesadmin.vm.QubesVM | None: """ Get currently selected VM, if any :return: QubesVM object @@ -498,9 +498,9 @@ class ImageListModeler(TraitSelector): def __init__( self, combobox: Gtk.ComboBox, - value_list: Dict[str, Dict[str, Any]], - event_callback: Optional[Callable[[], None]] = None, - selected_value: Optional[str] = None, + value_list: dict[str, dict[str, Any]], + event_callback: Callable[[], None] | None = None, + selected_value: str | None = None, style_changes: bool = False, ): """ @@ -522,7 +522,7 @@ def __init__( self.icon_size = 20 - self._entries: Dict[str, Dict[str, Any]] = value_list + self._entries: dict[str, dict[str, Any]] = value_list for entry in self._entries.values(): entry["loaded_icon"] = load_icon( @@ -609,7 +609,7 @@ def _event_callback(self, *_args): def __str__(self): return self.entry_box.get_text() - def get_selected(self) -> Optional[Any]: + def get_selected(self) -> Any: """ Get currently selected object, if any :return: any object @@ -633,9 +633,9 @@ class ImageTextButton(Gtk.Button): def __init__( self, icon_name: str, - label: Optional[str], - click_function: Optional[Callable[[Any], Any]] = None, - style_classes: Optional[List[str]] = None, + label: str | None, + click_function: Callable[[Any], Any] | None = None, + style_classes: list[str] | None = None, ): super().__init__() self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) @@ -707,10 +707,10 @@ def __init__( event_button: Gtk.Button, data_container: Gtk.Container, icon: Gtk.Image, - label: Optional[Gtk.Label] = None, - text_shown: Optional[str] = None, - text_hidden: Optional[str] = None, - event_callback: Optional[Callable[[bool], None]] = None, + label: Gtk.Label | None = None, + text_shown: str | None = None, + text_hidden: str | None = None, + event_callback: Callable[[bool], None] | None = None, ): """ :param event_button: Gtk.Button that collects the click event @@ -773,7 +773,7 @@ class ViewportHandler: def __init__( self, main_window: Gtk.Window, - scrolled_windows: List[Gtk.ScrolledWindow], + scrolled_windows: list[Gtk.ScrolledWindow], ): self.scrolled_windows = scrolled_windows self.main_window = main_window