Skip to content

Commit 8b289b4

Browse files
authored
Merge pull request #12 from axelande/adding_ci_test
Adding ci test
2 parents b14b4ca + 88bdc06 commit 8b289b4

File tree

3 files changed

+127
-35
lines changed

3 files changed

+127
-35
lines changed

.github/workflows/test_plugin.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3+
4+
name: Run tests
5+
6+
on:
7+
push:
8+
pull_request:
9+
branches:
10+
- 'main'
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
build:
17+
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- uses: actions/checkout@v3
22+
- name: Pull qgis image
23+
run: docker pull qgis/qgis:stable
24+
25+
- name: Pip install
26+
run: |
27+
docker run --name qgis_container --volume $(pwd):/app -w=/app qgis/qgis:stable sh -c "python3 -m pip install pytest-qgis --break-system-packages"
28+
docker commit qgis_container qgis_with_deps
29+
30+
- name: Run tests
31+
run: docker run --volume $(pwd):/app -w=/app qgis_with_deps sh -c "xvfb-run -s '+extension GLX -screen 0 1024x768x24' python3 -m pytest tests -s"

a00_qpip/plugin.py

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,18 @@
2020
class Plugin:
2121
"""QGIS Plugin Implementation."""
2222

23-
def __init__(self, iface):
23+
def __init__(self, iface, plugin_path=None):
2424
self.iface = iface
2525
self._defered_packages = []
2626
self.settings = QgsSettings()
2727
self.settings.beginGroup("QPIP")
2828

29-
self.plugins_path = os.path.join(
30-
QgsApplication.qgisSettingsDirPath(), "python", "plugins"
31-
)
29+
if plugin_path is None:
30+
self.plugins_path = os.path.join(
31+
QgsApplication.qgisSettingsDirPath(), "python", "plugins"
32+
)
33+
else:
34+
self.plugins_path = plugin_path
3235
self.prefix_path = os.path.join(
3336
QgsApplication.qgisSettingsDirPath().replace("/", os.path.sep),
3437
"python",
@@ -70,9 +73,10 @@ def initGui(self):
7073
def initComplete(self):
7174
if self._defered_packages:
7275
log(f"Initialization complete. Loading deferred packages")
73-
self.check_deps_and_prompt_install(
74-
additional_plugins=self._defered_packages
75-
)
76+
dialog, run_gui = self.check_deps(additional_plugins=self._defered_packages)
77+
if run_gui:
78+
self.promt_install(dialog)
79+
self.save_settings(dialog)
7680
self.start_packages(self._defered_packages)
7781
self._defered_packages = []
7882

@@ -91,7 +95,9 @@ def unload(self):
9195
os.environ["PYTHONPATH"] = os.environ["PYTHONPATH"].replace(
9296
self.bin_path + os.pathsep, ""
9397
)
94-
os.environ["PATH"] = os.environ["PATH"].replace(self.bin_path + os.pathsep, "")
98+
os.environ["PATH"] = os.environ["PATH"].replace(
99+
self.bin_path + os.pathsep, ""
100+
)
95101

96102
def patched_load_plugin(self, packageName):
97103
"""
@@ -118,14 +124,21 @@ def patched_load_plugin(self, packageName):
118124
return self._original_loadPlugin(packageName)
119125
else:
120126
log(f"Check on install enabled, we check {packageName}.")
121-
self.check_deps_and_prompt_install(additional_plugins=[packageName])
127+
dialog, run_gui = self.check_deps(additional_plugins=[packageName])
128+
if run_gui:
129+
self.promt_install(dialog)
130+
self.save_settings(dialog)
122131
self.start_packages([packageName])
123132
return True
124133

125-
def check_deps_and_prompt_install(self, additional_plugins=[], force_gui=False):
134+
def check_deps(self, additional_plugins=[]) -> MainDialog | bool:
126135
"""
127136
This checks dependencies for installed plugins and to-be installed plugins. If
128137
anything is missing, shows a GUI to install them.
138+
139+
The function returns:
140+
- MainDialog, the QDialog object (without opening it)
141+
- A bool if the dialog needs to be opened or not
129142
"""
130143

131144
plugin_names = [*qgis.utils.active_plugins, *additional_plugins]
@@ -165,31 +178,34 @@ def check_deps_and_prompt_install(self, additional_plugins=[], force_gui=False):
165178
req = Req(plugin_name, str(requirement), error)
166179
libs[requirement.key].name = requirement.key
167180
libs[requirement.key].required_by.append(req)
181+
dialog = MainDialog(
182+
libs.values(), self._check_on_startup(), self._check_on_install()
183+
)
184+
return dialog, needs_gui
185+
186+
def promt_install(self, dialog: MainDialog):
187+
"""Promts the install dialog and ask the user what to install"""
188+
if dialog.exec_():
189+
reqs_to_uninstall = dialog.reqs_to_uninstall
190+
if reqs_to_uninstall:
191+
log(f"Will uninstall selected dependencies : {reqs_to_uninstall}")
192+
self.pip_uninstall_reqs(reqs_to_uninstall)
193+
194+
reqs_to_install = dialog.reqs_to_install
195+
if reqs_to_install:
196+
log(f"Will install selected dependencies : {reqs_to_install}")
197+
self.pip_install_reqs(reqs_to_install)
198+
199+
def save_settings(self, dialog):
200+
"""Stores the settings values"""
201+
sys.path_importer_cache.clear()
168202

169-
if force_gui or needs_gui:
170-
dialog = MainDialog(
171-
libs.values(), self._check_on_startup(), self._check_on_install()
172-
)
173-
if dialog.exec_():
174-
reqs_to_uninstall = dialog.reqs_to_uninstall
175-
if reqs_to_uninstall:
176-
log(f"Will uninstall selected dependencies : {reqs_to_uninstall}")
177-
self.pip_uninstall_reqs(reqs_to_uninstall)
178-
179-
reqs_to_install = dialog.reqs_to_install
180-
if reqs_to_install:
181-
log(f"Will install selected dependencies : {reqs_to_install}")
182-
self.pip_install_reqs(reqs_to_install)
183-
184-
sys.path_importer_cache.clear()
185-
186-
# Save these even if the dialog was closed
187-
self.settings.setValue(
188-
"check_on_startup", "yes" if dialog.check_on_startup else "no"
189-
)
190-
self.settings.setValue(
191-
"check_on_install", "yes" if dialog.check_on_install else "no"
192-
)
203+
self.settings.setValue(
204+
"check_on_startup", "yes" if dialog.check_on_startup else "no"
205+
)
206+
self.settings.setValue(
207+
"check_on_install", "yes" if dialog.check_on_install else "no"
208+
)
193209

194210
def start_packages(self, packageNames):
195211
"""
@@ -249,7 +265,9 @@ def pip_install_reqs(self, reqs_to_install):
249265
)
250266

251267
def check(self):
252-
self.check_deps_and_prompt_install(force_gui=True)
268+
dialog, _ = self.check_deps()
269+
self.promt_install(dialog)
270+
self.save_settings(dialog)
253271

254272
def show_folder(self):
255273
if platform.system() == "Windows":

tests/test_finding_req.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
3+
import pytest
4+
5+
from a00_qpip.plugin import Plugin
6+
7+
8+
class initializationCompleted:
9+
def connect(self):
10+
pass
11+
12+
13+
def popWidget():
14+
return True
15+
16+
17+
THIS_DIR = os.path.dirname(__file__)
18+
19+
20+
@pytest.fixture()
21+
def plugin(qgis_iface):
22+
qgis_iface.initializationCompleted = initializationCompleted
23+
qgis_iface.messageBar().popWidget = popWidget
24+
plugin = Plugin(qgis_iface, ".")
25+
yield plugin
26+
27+
28+
def test_plugin_a(plugin: Plugin):
29+
plugin_a = os.path.join(THIS_DIR, "..", "test_plugins", "plugin_a")
30+
dialog, needs_gui = plugin.check_deps([plugin_a])
31+
libs = dialog.reqs_to_install
32+
assert len(libs) == 2
33+
assert libs[0] == "cowsay==4.0"
34+
assert needs_gui
35+
36+
37+
def test_plugin_b(plugin: Plugin):
38+
plugin_b = os.path.join(THIS_DIR, "..", "test_plugins", "plugin_b")
39+
dialog, needs_gui = plugin.check_deps([plugin_b])
40+
libs = dialog.reqs_to_install
41+
assert len(libs) == 2
42+
assert libs[0] == "cowsay==5.0"
43+
assert needs_gui

0 commit comments

Comments
 (0)