Skip to content

Commit

Permalink
Merge pull request #1190 from Ulauncher/refactor/Gio.Application.get_…
Browse files Browse the repository at this point in the history
…default

refactor:  Use gio.application.get_default() to avoid cyclic imports and unnecessary complexity
  • Loading branch information
friday committed Jan 21, 2023
2 parents 91cf95f + 21a7dcc commit aa850d0
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 54 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,5 @@ jobs:
- run: black --diff --check .
- run: flake8 .
- run: mypy .
# disabling cyclic-import since we want to see them but not error on them
# Can't override the error level unfortunately: https://github.com/PyCQA/pylint/issues/2293
# Might want to change pylint this to `pylint --errors-only ulauncher`,
# but I think most warnings should be trated as errors
- run: pylint --disable=cyclic-import ulauncher
- run: pylint ulauncher
- run: DISPLAY=:1 xvfb-run pytest tests
14 changes: 7 additions & 7 deletions tests/api/shared/action/test_RenderResultListAction.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from unittest import mock
import pytest

from ulauncher.ui.UlauncherApp import UlauncherApp
from ulauncher.api.shared.action.RenderResultListAction import RenderResultListAction


class TestRenderResultListAction:
@pytest.fixture(autouse=True)
def UlauncherApp(self, mocker):
app = mocker.patch("ulauncher.ui.UlauncherApp.UlauncherApp")
app.window = mocker.patch("ulauncher.ui.windows.UlauncherWindow.UlauncherWindow")()
return app
def UlauncherWindow(self, mocker):
app = UlauncherApp.get_instance()
app.window = mocker.patch("ulauncher.ui.windows.UlauncherWindow.UlauncherWindow").return_value
return app.window

@pytest.fixture(autouse=True)
def GLib(self, mocker):
Expand All @@ -26,6 +26,6 @@ def action(self, result_list):
def test_keep_app_open(self, action):
assert action.keep_app_open

def test_run(self, action, result_list, GLib, UlauncherApp):
def test_run(self, action, result_list, GLib, UlauncherWindow):
action.run()
GLib.idle_add.assert_called_with(UlauncherApp.get_instance.return_value.window.show_results, result_list)
GLib.idle_add.assert_called_with(UlauncherWindow.show_results, result_list)
13 changes: 7 additions & 6 deletions tests/modes/apps/extensions/test_DeferredResultRenderer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from unittest import mock
import pytest

from ulauncher.ui.UlauncherApp import UlauncherApp
from ulauncher.modes.extensions.DeferredResultRenderer import DeferredResultRenderer
from ulauncher.modes.extensions.ExtensionController import ExtensionController
from ulauncher.modes.extensions.ExtensionManifest import ExtensionManifest
Expand All @@ -11,10 +12,10 @@

class TestDeferredResultRenderer:
@pytest.fixture(autouse=True)
def UlauncherApp(self, mocker):
app = mocker.patch("ulauncher.ui.UlauncherApp.UlauncherApp")
app.window = mocker.patch("ulauncher.ui.windows.UlauncherWindow.UlauncherWindow")()
return app
def UlauncherWindow(self, mocker):
app = UlauncherApp.get_instance()
app.window = mocker.patch("ulauncher.ui.windows.UlauncherWindow.UlauncherWindow").return_value
return app.window

@pytest.fixture(autouse=True)
def timer(self, mocker):
Expand Down Expand Up @@ -58,14 +59,14 @@ def test_handle_response__action__is_ran(self, renderer, controller):
renderer.handle_response(response, controller)
response.action.run.assert_called_once_with()

def test_handle_response__keep_app_open_is_False__hide_is_called(self, renderer, controller, GLib, UlauncherApp):
def test_handle_response__keep_app_open_is_False__hide_is_called(self, renderer, controller, GLib, UlauncherWindow):
response = mock.Mock()
response.event = KeywordQueryEvent(Query("test"))
response.action.keep_app_open = False
renderer.active_event = response.event
renderer.active_controller = controller
renderer.handle_response(response, controller)
GLib.idle_add.assert_called_with(UlauncherApp.get_instance.return_value.window.hide_and_clear_input)
GLib.idle_add.assert_called_with(UlauncherWindow.hide_and_clear_input)

def test_on_query_change__loading__is_canceled(self, renderer):
timer = mock.Mock()
Expand Down
19 changes: 10 additions & 9 deletions tests/ui/test_preferences_server.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from gi.repository import Gio
from unittest import mock
import pytest
from ulauncher.utils.Settings import Settings
Expand All @@ -19,7 +20,11 @@ def check_json_prop(name):
class TestPreferencesContextServer:
@pytest.fixture(autouse=True)
def ulauncherWindow(self, mocker):
return mocker.patch("ulauncher.ui.windows.UlauncherWindow.UlauncherWindow").return_value
app = UlauncherApp.get_instance()
app.window = mocker.patch("ulauncher.ui.windows.UlauncherWindow.UlauncherWindow").return_value
app.toggle_appindicator = mock.MagicMock()
app.bind_hotkey = mock.MagicMock()
return app.window

@pytest.fixture(autouse=True)
def autostart_pref(self, mocker):
Expand All @@ -35,12 +40,8 @@ def hotkey_dialog(self, mocker):

# pylint: disable=too-many-arguments
@pytest.fixture
def prefs_server(self, webview, autostart_pref, ulauncherWindow):
app = UlauncherApp.get_instance()
app.window = ulauncherWindow
app.toggle_appindicator = mock.MagicMock()
app.bind_hotkey = mock.MagicMock()
server = PreferencesServer(app)
def prefs_server(self, webview, autostart_pref):
server = PreferencesServer()
server.autostart_pref = autostart_pref
server.settings = Settings.new_from_file(settings_file)
server.client = webview
Expand All @@ -49,14 +50,14 @@ def prefs_server(self, webview, autostart_pref, ulauncherWindow):
# pylint: disable=too-many-arguments
def test_apply_settings_show_indicator_icon(self, prefs_server):
prefs_server.apply_settings("show_indicator_icon", False)
prefs_server.app.toggle_appindicator.assert_called_with(False)
Gio.Application.get_default().toggle_appindicator.assert_called_with(False)
assert prefs_server.settings.show_indicator_icon is False
assert check_json_prop("show_indicator_icon") is False

def test_set_hotkey_show_app(self, prefs_server):
hotkey = "<Primary>space"
prefs_server.set_hotkey_show_app.original(prefs_server, hotkey)
prefs_server.app.bind_hotkey.assert_called_with(hotkey)
Gio.Application.get_default().bind_hotkey.assert_called_with(hotkey)
assert prefs_server.settings.hotkey_show_app == hotkey
assert check_json_prop("hotkey_show_app") == hotkey

Expand Down
16 changes: 11 additions & 5 deletions ulauncher/api/shared/action/RenderResultListAction.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from gi.repository import GLib
import logging
from gi.repository import Gio, GLib
from ulauncher.api.shared.action.BaseAction import BaseAction

logger = logging.getLogger()


class RenderResultListAction(BaseAction):
"""
Expand All @@ -16,9 +19,12 @@ def __init__(self, result_list):

def run(self):
# pylint: disable=import-outside-toplevel
from ulauncher.ui.UlauncherApp import UlauncherApp
app = Gio.Application.get_default()

window = UlauncherApp.get_instance().window
if window.is_visible():
if not app:
logger.error("RenderResultListAction.run() should only be called by Ulauncher")
elif not hasattr(app, "window") or not app.window.is_visible():
logger.warning("RenderResultListAction called, but no Ulauncher window is open")
else:
# update UI in the main thread to avoid race conditions
GLib.idle_add(window.show_results, self.result_list)
GLib.idle_add(app.window.show_results, self.result_list)
13 changes: 9 additions & 4 deletions ulauncher/api/shared/action/SetUserQueryAction.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from gi.repository import GLib
import logging
from gi.repository import Gio, GLib
from ulauncher.api.shared.action.BaseAction import BaseAction

logger = logging.getLogger()


class SetUserQueryAction(BaseAction):
"""
Expand All @@ -16,7 +19,9 @@ def run(self):
GLib.idle_add(self._update_query)

def _update_query(self):
# pylint: disable=import-outside-toplevel
from ulauncher.ui.UlauncherApp import UlauncherApp
app = Gio.Application.get_default()

UlauncherApp.get_instance().query = self.new_query
if app and hasattr(app, "query"):
app.query = self.new_query
else:
logger.error("SetUserQueryAction.run() should only be called by Ulauncher")
14 changes: 4 additions & 10 deletions ulauncher/modes/extensions/DeferredResultRenderer.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import logging
from functools import lru_cache
from gi.repository import GLib
from gi.repository import Gio, GLib

from ulauncher.api.result import Result
from ulauncher.api.shared.action.DoNothingAction import DoNothingAction
from ulauncher.api.shared.action.RenderResultListAction import RenderResultListAction
from ulauncher.utils.timer import timer

logger = logging.getLogger()


class DeferredResultRenderer:
"""
Expand Down Expand Up @@ -79,10 +76,7 @@ def _cancel_loading(self):
self.loading = None

def _hide_window(self):
# pylint: disable=import-outside-toplevel
from ulauncher.ui.UlauncherApp import UlauncherApp

window = UlauncherApp.get_instance().window
if window.is_visible():
app = Gio.Application.get_default()
if app and hasattr(app, "window") and app.window.is_visible():
# update UI in the main thread to avoid race conditions
GLib.idle_add(window.hide_and_clear_input)
GLib.idle_add(app.window.hide_and_clear_input)
13 changes: 6 additions & 7 deletions ulauncher/ui/preferences_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,10 @@ class PreferencesServer:

@classmethod
@lru_cache(maxsize=None)
def get_instance(cls, application):
return cls(application)
def get_instance(cls):
return cls()

def __init__(self, application):
self.app = application
def __init__(self):
self.autostart_pref = UlauncherSystemdController()
self.settings = Settings.load()
self.context = WebKit2.WebContext()
Expand Down Expand Up @@ -191,9 +190,9 @@ def apply_settings(self, property, value):
self.settings.save({property: value})

if property == "show_indicator_icon":
self.app.toggle_appindicator(value)
Gio.Application.get_default().toggle_appindicator(value)
if property == "theme_name":
self.app.window.apply_theme()
Gio.Application.get_default().window.apply_theme()

def apply_autostart(self, is_enabled):
logger.info("Set autostart-enabled to %s", is_enabled)
Expand All @@ -208,7 +207,7 @@ def apply_autostart(self, is_enabled):
@route("/set/hotkey-show-app")
@glib_idle_add
def set_hotkey_show_app(self, hotkey):
self.app.bind_hotkey(hotkey)
Gio.Application.get_default().bind_hotkey(hotkey)
self.settings.save(hotkey_show_app=hotkey)

@route("/show/hotkey-dialog")
Expand Down
2 changes: 1 addition & 1 deletion ulauncher/ui/windows/PreferencesWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def _init_webview(self):
hardware_acceleration_policy=WebKit2.HardwareAccelerationPolicy.NEVER,
)

server = PreferencesServer.get_instance(self.get_application())
server = PreferencesServer.get_instance()
self.webview = WebKit2.WebView(settings=settings, web_context=server.context)
server.client = self.webview
self.add(self.webview)
Expand Down

0 comments on commit aa850d0

Please sign in to comment.