From 222abcfbea3d673d72827c8fbe5c92bde6b37623 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 12:44:17 +0100 Subject: [PATCH 01/26] rework tests running --- .github/workflows/run-test.yml | 96 +++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 53370408..7782ad54 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -1,80 +1,90 @@ name: Run Mergin Plugin Tests -on: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: push: workflow_dispatch: inputs: PYTHON_API_CLIENT_VER: - description: 'python-api-client version: either a tag, release, or a branch' + description: "python-api-client version: either a tag, release, or a branch" required: true - default: 'master' + default: "master" type: string env: + CONDA_PKGS_DIRS: ~/conda_pkgs_dir + DEBIAN_FRONTEND: noninteractive + QT_QPA_PLATFORM: offscreen + XDG_RUNTIME_DIR: /tmp + QT_SCALE_FACTOR: 1 + QT_AUTO_SCREEN_SCALE_FACTOR: 0 + QT_FONT_DPI: 96 # Assign the version provided by 'workflow_dispatch' if available; otherwise, use the default. PYTHON_API_CLIENT_VER: ${{ inputs.PYTHON_API_CLIENT_VER != '' && inputs.PYTHON_API_CLIENT_VER || 'master' }} PLUGIN_NAME: Mergin - TEST_FUNCTION: suite.test_all - DOCKER_IMAGE: qgis/qgis -concurrency: - group: ci-${{github.ref}}-autotests - cancel-in-progress: true - jobs: run-tests: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: + fail-fast: false matrix: - docker_tags: [release-3_22, release-3_34] + qgis-version: + ["3.22", "3.28", "3.30", "3.32", "3.34", "3.40", "3.42", "3.44"] steps: + - name: Checkout plugin code + uses: actions/checkout@v6 + with: + path: plugin - - name: Checkout client code - uses: actions/checkout@v3 + - name: Checkout python-client + uses: actions/checkout@v6 with: repository: MerginMaps/python-api-client ref: ${{ env.PYTHON_API_CLIENT_VER }} path: client + - name: Cache conda packages + uses: actions/cache@v4 + with: + path: ~/conda_pkgs_dir + key: conda-pkgs-${{ runner.os }}-${{ matrix.qgis-version }} + + - name: Setup conda + uses: conda-incubator/setup-miniconda@v3 + with: + use-mamba: true + channels: conda-forge,defaults + + - name: Create environment and install QGIS + run: | + conda create -n qgis_env --no-default-packages --yes + conda install -n qgis_env qgis=${{ matrix.qgis-version }} pytest pytest-qt --yes + conda run -n qgis_env pip install --no-cache-dir pytest-qgis + # mergin cilent dependencies + conda run -n qgis_env pip install python-dateutil pytz wheel + - name: Install python-api-client dependencies run: | - pip3 install python-dateutil pytz wheel cd client mkdir -p mergin/deps - pip3 install pygeodiff --target=mergin/deps - python3 setup.py sdist bdist_wheel + conda run -n qgis_env pip install pygeodiff --target=mergin/deps + conda run -n qgis_env python setup.py sdist bdist_wheel # without __init__.py the deps dir may get recognized as "namespace package" in python # and it can break qgis plugin unloading mechanism - see #126 touch mergin/deps/__init__.py - pip3 wheel -r mergin_client.egg-info/requires.txt -w mergin/deps + conda run -n qgis_env pip wheel -r mergin_client.egg-info/requires.txt -w mergin/deps unzip -o mergin/deps/pygeodiff-*.whl -d mergin/deps - - name: Checkout plugin code - uses: actions/checkout@v3 - with: - path: plugin - - - name: Copy client files to the plugin directory - run: | - cp -r client/mergin plugin/Mergin - - - name: Docker pull and create qgis-testing-environment - run: | - docker pull "$DOCKER_IMAGE":${{ matrix.docker_tags }} - docker run -d --name qgis-testing-environment -v "$GITHUB_WORKSPACE"/plugin:/tests_directory -e DISPLAY=:99 "$DOCKER_IMAGE":${{ matrix.docker_tags }} - # Wait for xvfb to finish starting - printf "Waiting for the docker...🐳..." - sleep 10 - echo " done 🥩" + - name: Copy client files to plugin directory + run: cp -r client/mergin plugin/${{ env.PLUGIN_NAME }} - - name: Docker set up QGIS - run: | - docker exec qgis-testing-environment sh -c "qgis_setup.sh $PLUGIN_NAME" - docker exec qgis-testing-environment sh -c "rm -f /root/.local/share/QGIS/QGIS3/profiles/default/python/plugins/$PLUGIN_NAME" - docker exec qgis-testing-environment sh -c "ln -s /tests_directory/$PLUGIN_NAME /root/.local/share/QGIS/QGIS3/profiles/default/python/plugins/$PLUGIN_NAME" - - - name: Docker run plugin tests - run: | - docker exec qgis-testing-environment sh -c "cd /tests_directory/$PLUGIN_NAME/test && qgis_testrunner.sh $TEST_FUNCTION" + - name: Run tests + run: conda run -n qgis_env pytest plugin/${{ env.PLUGIN_NAME }}/test -v + env: + PYTHONPATH: ${{ github.workspace }}/plugin From a4bb734f680ca1eec5736892ea8dfec4ea017da9 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 12:50:56 +0100 Subject: [PATCH 02/26] only test on one version for now --- .github/workflows/run-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 7782ad54..0762b890 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -34,7 +34,8 @@ jobs: fail-fast: false matrix: qgis-version: - ["3.22", "3.28", "3.30", "3.32", "3.34", "3.40", "3.42", "3.44"] + ["3.44"] + # ["3.22", "3.28", "3.30", "3.32", "3.34", "3.40", "3.42", "3.44"] steps: - name: Checkout plugin code From 98adb71d34f46e6f3767e8e068a76b3f43f271d9 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 12:53:32 +0100 Subject: [PATCH 03/26] list plugin files --- .github/workflows/run-test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 0762b890..0f406469 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -85,6 +85,10 @@ jobs: - name: Copy client files to plugin directory run: cp -r client/mergin plugin/${{ env.PLUGIN_NAME }} + - name: List plugin directory contents + run: | + ls -R plugin/${{ env.PLUGIN_NAME }} + - name: Run tests run: conda run -n qgis_env pytest plugin/${{ env.PLUGIN_NAME }}/test -v env: From 1ee22609946728699c9f50b9de4a690c4b705295 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 13:02:29 +0100 Subject: [PATCH 04/26] move test --- tests/test_help.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/test_help.py diff --git a/tests/test_help.py b/tests/test_help.py new file mode 100644 index 00000000..2ec15ef1 --- /dev/null +++ b/tests/test_help.py @@ -0,0 +1,18 @@ +# GPLv3 license +# Copyright Lutra Consulting Limited + +import urllib.request + +from Mergin.help import MerginHelp + + +def test_help_urls(): + mh = MerginHelp() + + req = urllib.request.Request(mh.howto_attachment_widget(), method="HEAD") + resp = urllib.request.urlopen(req) + assert resp.status == 200 + + req = urllib.request.Request(mh.howto_background_maps(), method="HEAD") + resp = urllib.request.urlopen(req) + assert resp.status == 200 From 3c9ade2fba7c2bab24d566b0bfa969f924e0b4b5 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 13:02:42 +0100 Subject: [PATCH 05/26] run tests from another place --- .github/workflows/run-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 0f406469..094a9575 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -90,6 +90,6 @@ jobs: ls -R plugin/${{ env.PLUGIN_NAME }} - name: Run tests - run: conda run -n qgis_env pytest plugin/${{ env.PLUGIN_NAME }}/test -v + run: conda run -n qgis_env pytest tests --cov=Mergin --cov-report=term-missing:skip-covered -rP -vv -s env: PYTHONPATH: ${{ github.workspace }}/plugin From 3f820243a482c57451c95d77647c5013b7f2b7be Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 13:22:16 +0100 Subject: [PATCH 06/26] add pytest-cov --- .github/workflows/run-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 094a9575..7751d394 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -65,7 +65,7 @@ jobs: - name: Create environment and install QGIS run: | conda create -n qgis_env --no-default-packages --yes - conda install -n qgis_env qgis=${{ matrix.qgis-version }} pytest pytest-qt --yes + conda install -n qgis_env qgis=${{ matrix.qgis-version }} pytest pytest-qt pytest-cov --yes conda run -n qgis_env pip install --no-cache-dir pytest-qgis # mergin cilent dependencies conda run -n qgis_env pip install python-dateutil pytz wheel From a9e8cc29cd979ee94c69e22260d23894d7776fe7 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 13:28:16 +0100 Subject: [PATCH 07/26] fix path --- .github/workflows/run-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 7751d394..e9bdf6b0 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -90,6 +90,6 @@ jobs: ls -R plugin/${{ env.PLUGIN_NAME }} - name: Run tests - run: conda run -n qgis_env pytest tests --cov=Mergin --cov-report=term-missing:skip-covered -rP -vv -s + run: conda run -n qgis_env pytest ${{ github.workspace }}/plugin/tests --cov=Mergin --cov-report=term-missing:skip-covered -rP -vv -s env: PYTHONPATH: ${{ github.workspace }}/plugin From 159b338438bc62e099b116927f80df78cc2366fc Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 13:59:39 +0100 Subject: [PATCH 08/26] move tests data --- {Mergin/test => tests}/data/dem.prj | 0 {Mergin/test => tests}/data/dem.qpj | 0 {Mergin/test => tests}/data/dem.tfw | 0 {Mergin/test => tests}/data/dem.tif | Bin {Mergin/test => tests}/data/dem.tifw | 0 {Mergin/test => tests}/data/dem.wld | 0 {Mergin/test => tests}/data/raster-tiles.mbtiles | Bin {Mergin/test => tests}/data/schema_base.json | 0 {Mergin/test => tests}/data/schema_two_tables.json | 0 {Mergin/test => tests}/data/transport_aerodrome.svg | 0 {Mergin/test => tests}/data/vector-tiles.mbtiles | Bin 11 files changed, 0 insertions(+), 0 deletions(-) rename {Mergin/test => tests}/data/dem.prj (100%) rename {Mergin/test => tests}/data/dem.qpj (100%) rename {Mergin/test => tests}/data/dem.tfw (100%) rename {Mergin/test => tests}/data/dem.tif (100%) rename {Mergin/test => tests}/data/dem.tifw (100%) rename {Mergin/test => tests}/data/dem.wld (100%) rename {Mergin/test => tests}/data/raster-tiles.mbtiles (100%) rename {Mergin/test => tests}/data/schema_base.json (100%) rename {Mergin/test => tests}/data/schema_two_tables.json (100%) rename {Mergin/test => tests}/data/transport_aerodrome.svg (100%) rename {Mergin/test => tests}/data/vector-tiles.mbtiles (100%) diff --git a/Mergin/test/data/dem.prj b/tests/data/dem.prj similarity index 100% rename from Mergin/test/data/dem.prj rename to tests/data/dem.prj diff --git a/Mergin/test/data/dem.qpj b/tests/data/dem.qpj similarity index 100% rename from Mergin/test/data/dem.qpj rename to tests/data/dem.qpj diff --git a/Mergin/test/data/dem.tfw b/tests/data/dem.tfw similarity index 100% rename from Mergin/test/data/dem.tfw rename to tests/data/dem.tfw diff --git a/Mergin/test/data/dem.tif b/tests/data/dem.tif similarity index 100% rename from Mergin/test/data/dem.tif rename to tests/data/dem.tif diff --git a/Mergin/test/data/dem.tifw b/tests/data/dem.tifw similarity index 100% rename from Mergin/test/data/dem.tifw rename to tests/data/dem.tifw diff --git a/Mergin/test/data/dem.wld b/tests/data/dem.wld similarity index 100% rename from Mergin/test/data/dem.wld rename to tests/data/dem.wld diff --git a/Mergin/test/data/raster-tiles.mbtiles b/tests/data/raster-tiles.mbtiles similarity index 100% rename from Mergin/test/data/raster-tiles.mbtiles rename to tests/data/raster-tiles.mbtiles diff --git a/Mergin/test/data/schema_base.json b/tests/data/schema_base.json similarity index 100% rename from Mergin/test/data/schema_base.json rename to tests/data/schema_base.json diff --git a/Mergin/test/data/schema_two_tables.json b/tests/data/schema_two_tables.json similarity index 100% rename from Mergin/test/data/schema_two_tables.json rename to tests/data/schema_two_tables.json diff --git a/Mergin/test/data/transport_aerodrome.svg b/tests/data/transport_aerodrome.svg similarity index 100% rename from Mergin/test/data/transport_aerodrome.svg rename to tests/data/transport_aerodrome.svg diff --git a/Mergin/test/data/vector-tiles.mbtiles b/tests/data/vector-tiles.mbtiles similarity index 100% rename from Mergin/test/data/vector-tiles.mbtiles rename to tests/data/vector-tiles.mbtiles From 3941b4b7da909c90df79b5745b5bb655765bdd3e Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 14:00:19 +0100 Subject: [PATCH 09/26] conftest --- tests/conftest.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..68f36a56 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +# GPLv3 license +# Copyright Lutra Consulting Limited + +from pathlib import Path + +import pytest +from qgis.core import QgsVectorLayer + + +@pytest.fixture +def test_data_path() -> Path: + """Fixture for test data path.""" + return Path(__file__).parent / "data" + + +@pytest.fixture +def mem_layer() -> QgsVectorLayer: + """Fixture for an in-memory vector layer.""" + return QgsVectorLayer("Point", "test", "memory") + + +@pytest.fixture +def dem_tif_path(test_data_path: Path) -> Path: + """Fixture for DEM TIFF file path.""" + return test_data_path / "dem.tif" + + +@pytest.fixture +def raster_tiles_path(test_data_path: Path) -> Path: + """Fixture for raster tiles MBTiles file path.""" + return test_data_path / "raster-tiles.mbtiles" + + +@pytest.fixture +def vector_tiles_path(test_data_path: Path) -> Path: + """Fixture for vector tiles MBTiles file path.""" + return test_data_path / "vector-tiles.mbtiles" From f62926f99d3883a0b85af03ca30c165e4cf2abca Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 14:00:25 +0100 Subject: [PATCH 10/26] update --- tests/test_help.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_help.py b/tests/test_help.py index 2ec15ef1..138a4cd9 100644 --- a/tests/test_help.py +++ b/tests/test_help.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + # GPLv3 license # Copyright Lutra Consulting Limited From faf6ad78aef51cad9609587f53ba604a9b53a296 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 25 Mar 2026 14:00:37 +0100 Subject: [PATCH 11/26] test packaging --- tests/test_packaging.py | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/test_packaging.py diff --git a/tests/test_packaging.py b/tests/test_packaging.py new file mode 100644 index 00000000..5797c292 --- /dev/null +++ b/tests/test_packaging.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + +# GPLv3 license +# Copyright Lutra Consulting Limited + + +import os +import tempfile +from pathlib import Path + +from qgis.core import QgsRasterLayer, QgsVectorTileLayer, QgsProviderRegistry + + +from Mergin.utils import package_layer + +test_data_path = os.path.join(os.path.dirname(__file__), "data") + + +def test_copy_raster(dem_tif_path: Path): + """Test packaging of raster layer and updating data source.""" + + layer = QgsRasterLayer(dem_tif_path.as_posix(), "test", "gdal") + + assert layer.isValid() + + source_raster_uri = layer.dataProvider().dataSourceUri() + + assert source_raster_uri == dem_tif_path.as_posix() + + with tempfile.TemporaryDirectory() as tmp_dir: + package_layer(layer, tmp_dir) + for ext in ("tif", "wld", "tfw", "prj", "qpj", "tifw"): + expected_filepath = Path(tmp_dir) / f"dem.{ext}" + assert expected_filepath.exists() + + if ext == "tif": + # Check if raster data source was updated + destination_raster_uri = layer.dataProvider().dataSourceUri() + assert destination_raster_uri == expected_filepath.as_posix() + + +def test_mbtiles_packaging(raster_tiles_path: Path, vector_tiles_path: Path): + """Test packaging of raster and vector tiles layers and updating data source.""" + + layer = QgsRasterLayer(f"url=file://{raster_tiles_path.as_posix()}&type=mbtiles", "test", "wms") + + assert layer.isValid() + + with tempfile.TemporaryDirectory() as tmp_dir: + package_layer(layer, tmp_dir) + expected_path = Path(tmp_dir) / "raster-tiles.mbtiles" + assert expected_path.exists() + + uri = QgsProviderRegistry.instance().decodeUri("wms", layer.source()) + assert str(uri) + assert "path" in uri + assert uri["path"] == expected_path.as_posix() + + layer = QgsVectorTileLayer(f"url=file://{vector_tiles_path.as_posix()}&type=mbtiles", "test") + assert layer.isValid() + + with tempfile.TemporaryDirectory() as tmp_dir: + package_layer(layer, tmp_dir) + expected_path = Path(tmp_dir) / "vector-tiles.mbtiles" + + assert expected_path.exists() + + uri = QgsProviderRegistry.instance().decodeUri("vectortile", layer.source()) + assert "path" in uri + assert uri["path"] == expected_path.as_posix() From 99c5e0253f2bda760ae98d92266ea26a45aa83a1 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 27 Mar 2026 15:14:24 +0100 Subject: [PATCH 12/26] add conda env for testing --- environment.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 environment.yml diff --git a/environment.yml b/environment.yml new file mode 100644 index 00000000..52f29c4a --- /dev/null +++ b/environment.yml @@ -0,0 +1,15 @@ +name: qgis-test-env +channels: + - conda-forge + - defaults +dependencies: + - qgis + - pytest + - pytest-qt + - pytest-cov + - pip + - pip: + - pytest-qgis + - python-dateutil + - pytz + - wheel From 4e74ecabd898bc2b17cce59b280622a3a194c61e Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 27 Mar 2026 15:14:45 +0100 Subject: [PATCH 13/26] ignore .qgis-settings folder created when running tests --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d3ed02f..1b977a7d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ Mergin/mergin .idea/ .DS_Store mergin-py-client +.qgis-settings From 9333ee226b5b0c7fb50c28e84b8337396ca229d5 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 27 Mar 2026 15:17:28 +0100 Subject: [PATCH 14/26] split into separate tests --- tests/test_packaging.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 5797c292..2910c254 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -8,8 +8,7 @@ import tempfile from pathlib import Path -from qgis.core import QgsRasterLayer, QgsVectorTileLayer, QgsProviderRegistry - +from qgis.core import QgsProviderRegistry, QgsRasterLayer, QgsVectorTileLayer from Mergin.utils import package_layer @@ -39,32 +38,35 @@ def test_copy_raster(dem_tif_path: Path): assert destination_raster_uri == expected_filepath.as_posix() -def test_mbtiles_packaging(raster_tiles_path: Path, vector_tiles_path: Path): +def test_mbtiles_packaging_raster_layer(raster_tiles_path: Path): """Test packaging of raster and vector tiles layers and updating data source.""" - layer = QgsRasterLayer(f"url=file://{raster_tiles_path.as_posix()}&type=mbtiles", "test", "wms") + rlayer = QgsRasterLayer(f"url=file://{raster_tiles_path.as_posix()}&type=mbtiles", "test", "wms") - assert layer.isValid() + assert rlayer.isValid() with tempfile.TemporaryDirectory() as tmp_dir: - package_layer(layer, tmp_dir) + package_layer(rlayer, tmp_dir) expected_path = Path(tmp_dir) / "raster-tiles.mbtiles" assert expected_path.exists() - uri = QgsProviderRegistry.instance().decodeUri("wms", layer.source()) + uri = QgsProviderRegistry.instance().decodeUri("wms", rlayer.source()) assert str(uri) assert "path" in uri assert uri["path"] == expected_path.as_posix() - layer = QgsVectorTileLayer(f"url=file://{vector_tiles_path.as_posix()}&type=mbtiles", "test") - assert layer.isValid() + +def test_mbtiles_packaging_vector_tile_layer(vector_tiles_path: Path): + + vlayer = QgsVectorTileLayer(f"url=file://{vector_tiles_path.as_posix()}&type=mbtiles", "test") + assert vlayer.isValid() with tempfile.TemporaryDirectory() as tmp_dir: - package_layer(layer, tmp_dir) + package_layer(vlayer, tmp_dir) expected_path = Path(tmp_dir) / "vector-tiles.mbtiles" assert expected_path.exists() - uri = QgsProviderRegistry.instance().decodeUri("vectortile", layer.source()) + uri = QgsProviderRegistry.instance().decodeUri("vectortile", vlayer.source()) assert "path" in uri assert uri["path"] == expected_path.as_posix() From 819c5b15f4e7bb61ff78c9b7c441fc8f46fd3496 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 27 Mar 2026 15:17:46 +0100 Subject: [PATCH 15/26] add fixtures --- tests/conftest.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 68f36a56..6345f7b1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,10 +3,12 @@ # GPLv3 license # Copyright Lutra Consulting Limited +import json from pathlib import Path +from typing import Dict import pytest -from qgis.core import QgsVectorLayer +from qgis.core import QgsProject, QgsVectorLayer @pytest.fixture @@ -37,3 +39,27 @@ def raster_tiles_path(test_data_path: Path) -> Path: def vector_tiles_path(test_data_path: Path) -> Path: """Fixture for vector tiles MBTiles file path.""" return test_data_path / "vector-tiles.mbtiles" + + +@pytest.fixture +def base_schema(test_data_path: Path) -> Dict: + """Fixture for base schema used in tests.""" + with open(test_data_path / "schema_base.json") as f: + return json.load(f).get("geodiff_schema") + + +@pytest.fixture +def tables_schema(test_data_path: Path) -> Dict: + """Fixture for tables schema used in tests.""" + with open(test_data_path / "schema_two_tables.json") as f: + return json.load(f).get("geodiff_schema") + + +@pytest.fixture +def project_dir(mem_layer: QgsVectorLayer, tmp_path: Path) -> Path: + """Fixture for a QGIS project directory.""" + proj = QgsProject.instance() + proj.addMapLayer(mem_layer) + proj.setFileName(str(tmp_path / "test_project.qgz")) + yield tmp_path + proj.removeMapLayer(mem_layer.id()) From 608c02e5b679c1ad11a6426b24f6062e0d48a2bb Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 27 Mar 2026 15:18:01 +0100 Subject: [PATCH 16/26] move tests --- tests/test_utils.py | 231 ++++++++++++++++++++++++++++++++++++++ tests/test_validations.py | 228 +++++++++++++++++++++++++++++++++++++ 2 files changed, 459 insertions(+) create mode 100644 tests/test_utils.py create mode 100644 tests/test_validations.py diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 00000000..ce09e809 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,231 @@ +# -*- coding: utf-8 -*- + +# GPLv3 license +# Copyright Lutra Consulting Limited + + +import copy +import tempfile +from pathlib import Path +from typing import Dict + +from qgis.core import ( + QgsCoordinateReferenceSystem, + QgsCoordinateTransformContext, + QgsDatumTransform, + QgsProject, + QgsSymbolLayer, + QgsVectorLayer, + QgsWkbTypes, +) +from qgis.PyQt.QtCore import QVariant + +from Mergin.utils import ( + create_map_sketches_layer, + create_tracking_layer, + get_datum_shift_grids, + is_valid_name, + same_schema, +) + + +def test_table_added_removed(base_schema: Dict, tables_schema: Dict): + equal, msg = same_schema(base_schema, base_schema) + assert equal + assert msg == "No schema changes" + + equal, msg = same_schema(base_schema, tables_schema) + assert not equal + assert msg == "Tables added/removed: added: hotels" + + equal, msg = same_schema(tables_schema, base_schema) + assert not equal + assert msg == "Tables added/removed: removed: hotels" + + +def test_table_schema_changed(base_schema: Dict): + modified_schema = copy.deepcopy(base_schema) + + # change column name from fid to id + modified_schema[0]["columns"][0]["name"] = "id" + equal, msg = same_schema(base_schema, modified_schema) + assert not equal + assert msg == "Fields in table 'Survey_points' added/removed: added: id; removed: fid" + modified_schema[0]["columns"][0]["name"] = "fid" + + # change column type from datetime to date + modified_schema[0]["columns"][2]["type"] = "date" + equal, msg = same_schema(base_schema, modified_schema) + assert not equal + assert msg == "Definition of 'date' field in 'Survey_points' table is not the same" + + +def test_datum_shift_grids(): + grids = get_datum_shift_grids() + assert len(grids) == 0 + + crs_a = QgsCoordinateReferenceSystem("EPSG:27700") + crs_b = QgsCoordinateReferenceSystem("EPSG:3857") + ops = QgsDatumTransform.operations(crs_a, crs_b) + assert len(ops) > 0 + proj_str = ops[0].proj + + context = QgsCoordinateTransformContext() + context.addCoordinateOperation(crs_a, crs_b, proj_str) + QgsProject.instance().setTransformContext(context) + + # if there are no layers which use datum transformations nothing should be returned + grids = get_datum_shift_grids() + assert len(grids) == 0 + + layer = QgsVectorLayer("Point?crs=EPSG:27700", "", "memory") + QgsProject.instance().addMapLayer(layer) + QgsProject.instance().setCrs(crs_b) + + grids = get_datum_shift_grids() + assert len(grids) == 1 + assert "uk_os_OSTN15_NTv2_OSGBtoETRS.tif" in grids or "OSTN15_NTv2_OSGBtoETRS.gsb" in grids + + QgsProject.instance().removeMapLayer(layer.id()) + + +def test_name_validation(): + test_cases = [ + ("project", True), + ("ProJect", True), + ("Pro123ject", True), + ("123PROJECT", True), + ("PROJECT", True), + ("project ", True), + ("pro ject", True), + ("proj-ect", True), + ("-project", True), + ("proj_ect", True), + ("proj.ect", True), + ("proj!ect", True), + (" project", False), + (".project", False), + ("proj~ect", False), + (r"pro\ject", False), + ("pro/ject", False), + ("pro|ject", False), + ("pro+ject", False), + ("pro=ject", False), + ("pro>ject", False), + ("pro Date: Fri, 27 Mar 2026 15:18:22 +0100 Subject: [PATCH 17/26] add pyproject with settings --- pyproject.toml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..133b5a06 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[options.extras_require] +test = ["pytest", "pytest-cov", "pytest-qgis"] + +[tool.pytest.ini_options] +addopts = "-rP -vv -s" +testpaths = ["tests"] +pythonpath = ["."] + +[tool.black] +line-length = 120 + +[tool.isort] +atomic = true +profile = "black" +line_length = 120 From 065b7df806488e579a078b4c982d9e614a346e03 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Fri, 27 Mar 2026 15:18:53 +0100 Subject: [PATCH 18/26] remove tests --- Mergin/test/__init__.py | 0 Mergin/test/suite.py | 27 ---- Mergin/test/test_help.py | 45 ------ Mergin/test/test_packaging.py | 64 -------- Mergin/test/test_utils.py | 260 -------------------------------- Mergin/test/test_validations.py | 248 ------------------------------ 6 files changed, 644 deletions(-) delete mode 100644 Mergin/test/__init__.py delete mode 100644 Mergin/test/suite.py delete mode 100644 Mergin/test/test_help.py delete mode 100644 Mergin/test/test_packaging.py delete mode 100644 Mergin/test/test_utils.py delete mode 100644 Mergin/test/test_validations.py diff --git a/Mergin/test/__init__.py b/Mergin/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/Mergin/test/suite.py b/Mergin/test/suite.py deleted file mode 100644 index 775298d0..00000000 --- a/Mergin/test/suite.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- - -# GPLv3 license -# Copyright Lutra Consulting Limited - - -import sys -import unittest - - -def _run_tests(test_suite, package_name): - count = test_suite.countTestCases() - print("########") - print("{} tests has been discovered in {}".format(count, package_name)) - print("########") - - unittest.TextTestRunner(verbosity=3, stream=sys.stdout).run(test_suite) - - -def test_all(package="."): - test_loader = unittest.defaultTestLoader - test_suite = test_loader.discover(package) - _run_tests(test_suite, package) - - -if __name__ == "__main__": - test_all() diff --git a/Mergin/test/test_help.py b/Mergin/test/test_help.py deleted file mode 100644 index 8d60d1a9..00000000 --- a/Mergin/test/test_help.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- - -# GPLv3 license -# Copyright Lutra Consulting Limited - - -import os -import urllib.request -from qgis.core import ( - QgsVectorLayer, -) -from qgis.testing import start_app, unittest -from Mergin.help import MerginHelp - -test_data_path = os.path.join(os.path.dirname(__file__), "data") - - -class test_help(unittest.TestCase): - @classmethod - def setUpClass(cls): - start_app() - - def test_help_urls(self): - mh = MerginHelp() - - req = urllib.request.Request(mh.howto_attachment_widget(), method="HEAD") - resp = urllib.request.urlopen(req) - self.assertEqual(resp.status, 200) - - req = urllib.request.Request(mh.howto_background_maps(), method="HEAD") - resp = urllib.request.urlopen(req) - self.assertEqual(resp.status, 200) - - -def create_mem_layer() -> QgsVectorLayer: - """ - Create a memory layer. - """ - layer = QgsVectorLayer("Point", "test", "memory") - - return layer - - -if __name__ == "__main__": - nose2.main() diff --git a/Mergin/test/test_packaging.py b/Mergin/test/test_packaging.py deleted file mode 100644 index 40776040..00000000 --- a/Mergin/test/test_packaging.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- - -# GPLv3 license -# Copyright Lutra Consulting Limited - - -import os -import tempfile - -from qgis.core import QgsRasterLayer, QgsVectorTileLayer, QgsProviderRegistry - -from qgis.testing import start_app, unittest -from Mergin.utils import package_layer - -test_data_path = os.path.join(os.path.dirname(__file__), "data") - - -class test_packaging(unittest.TestCase): - @classmethod - def setUpClass(cls): - start_app() - - def test_copy_raster(self): - test_data_raster_path = os.path.join(test_data_path, "dem.tif") - layer = QgsRasterLayer(test_data_raster_path, "test", "gdal") - self.assertTrue(layer.isValid()) - source_raster_uri = layer.dataProvider().dataSourceUri() - self.assertEqual(source_raster_uri, test_data_raster_path) - with tempfile.TemporaryDirectory() as tmp_dir: - package_layer(layer, tmp_dir) - for ext in ("tif", "wld", "tfw", "prj", "qpj", "tifw"): - expected_filepath = os.path.join(tmp_dir, f"dem.{ext}") - self.assertTrue(os.path.exists(expected_filepath)) - if ext == "tif": - # Check if raster data source was updated - destination_raster_uri = layer.dataProvider().dataSourceUri() - self.assertEqual(destination_raster_uri, expected_filepath) - - def test_mbtiles_packaging(self): - raster_tiles_path = os.path.join(test_data_path, "raster-tiles.mbtiles") - layer = QgsRasterLayer(f"url=file://{raster_tiles_path}&type=mbtiles", "test", "wms") - self.assertTrue(layer.isValid()) - with tempfile.TemporaryDirectory() as tmp_dir: - package_layer(layer, tmp_dir) - expected_path = os.path.join(tmp_dir, "raster-tiles.mbtiles") - self.assertTrue(os.path.exists(expected_path)) - uri = QgsProviderRegistry.instance().decodeUri("wms", layer.source()) - self.assertTrue("path" in uri, str(uri)) - self.assertEqual(uri["path"], expected_path) - - vector_tiles_path = os.path.join(test_data_path, "vector-tiles.mbtiles") - layer = QgsVectorTileLayer(f"url={vector_tiles_path}&type=mbtiles", "test") - self.assertTrue(layer.isValid()) - with tempfile.TemporaryDirectory() as tmp_dir: - package_layer(layer, tmp_dir) - expected_path = os.path.join(tmp_dir, "vector-tiles.mbtiles") - self.assertTrue(os.path.exists(expected_path)) - uri = QgsProviderRegistry.instance().decodeUri("vectortile", layer.source()) - self.assertTrue("path" in uri) - self.assertEqual(uri["path"], expected_path) - - -if __name__ == "__main__": - nose2.main() diff --git a/Mergin/test/test_utils.py b/Mergin/test/test_utils.py deleted file mode 100644 index 9c3b575a..00000000 --- a/Mergin/test/test_utils.py +++ /dev/null @@ -1,260 +0,0 @@ -# -*- coding: utf-8 -*- - -# GPLv3 license -# Copyright Lutra Consulting Limited - - -import os -import json -import copy -import tempfile - -from qgis.PyQt.QtCore import QVariant -from qgis.core import ( - QgsProject, - QgsDatumTransform, - QgsCoordinateReferenceSystem, - QgsCoordinateTransformContext, - QgsVectorLayer, - QgsWkbTypes, - QgsSymbolLayer, -) - -from qgis.testing import start_app, unittest -from Mergin.utils import ( - same_schema, - get_datum_shift_grids, - is_valid_name, - create_tracking_layer, - create_map_sketches_layer, -) - -test_data_path = os.path.join(os.path.dirname(__file__), "data") - - -class test_utils(unittest.TestCase): - @classmethod - def setUpClass(cls): - start_app() - - def tearDown(self): - del self.base_schema - del self.tables_schema - - def setUp(self): - with open(os.path.join(test_data_path, "schema_base.json")) as f: - self.base_schema = json.load(f).get("geodiff_schema") - - with open(os.path.join(test_data_path, "schema_two_tables.json")) as f: - self.tables_schema = json.load(f).get("geodiff_schema") - - def test_table_added_removed(self): - equal, msg = same_schema(self.base_schema, self.base_schema) - self.assertTrue(equal) - self.assertEqual(msg, "No schema changes") - - equal, msg = same_schema(self.base_schema, self.tables_schema) - self.assertFalse(equal) - self.assertEqual(msg, "Tables added/removed: added: hotels") - - equal, msg = same_schema(self.tables_schema, self.base_schema) - self.assertFalse(equal) - self.assertEqual(msg, "Tables added/removed: removed: hotels") - - def test_table_schema_changed(self): - modified_schema = copy.deepcopy(self.base_schema) - - # change column name from fid to id - modified_schema[0]["columns"][0]["name"] = "id" - equal, msg = same_schema(self.base_schema, modified_schema) - self.assertFalse(equal) - self.assertEqual( - msg, - "Fields in table 'Survey_points' added/removed: added: id; removed: fid", - ) - modified_schema[0]["columns"][0]["name"] = "fid" - - # change column type from datetime to date - modified_schema[0]["columns"][2]["type"] = "date" - equal, msg = same_schema(self.base_schema, modified_schema) - self.assertFalse(equal) - self.assertEqual(msg, "Definition of 'date' field in 'Survey_points' table is not the same") - - def test_datum_shift_grids(self): - grids = get_datum_shift_grids() - self.assertEqual(len(grids), 0) - - crs_a = QgsCoordinateReferenceSystem("EPSG:27700") - crs_b = QgsCoordinateReferenceSystem("EPSG:3857") - ops = QgsDatumTransform.operations(crs_a, crs_b) - self.assertTrue(len(ops) > 0) - proj_str = ops[0].proj - - context = QgsCoordinateTransformContext() - context.addCoordinateOperation(crs_a, crs_b, proj_str) - QgsProject.instance().setTransformContext(context) - - # if there are no layers which use datum transformtaions nothing - # should be returned - grids = get_datum_shift_grids() - self.assertEqual(len(grids), 0) - - layer = QgsVectorLayer("Point?crs=EPSG:27700", "", "memory") - QgsProject.instance().addMapLayer(layer) - QgsProject.instance().setCrs(crs_b) - - grids = get_datum_shift_grids() - self.assertEqual(len(grids), 1) - self.assertTrue("uk_os_OSTN15_NTv2_OSGBtoETRS.tif" in grids or "OSTN15_NTv2_OSGBtoETRS.gsb" in grids) - - def test_name_validation(self): - test_cases = [ - ("project", True), - ("ProJect", True), - ("Pro123ject", True), - ("123PROJECT", True), - ("PROJECT", True), - ("project ", True), - ("pro ject", True), - ("proj-ect", True), - ("-project", True), - ("proj_ect", True), - ("proj.ect", True), - ("proj!ect", True), - (" project", False), - (".project", False), - ("proj~ect", False), - (r"pro\ject", False), - ("pro/ject", False), - ("pro|ject", False), - ("pro+ject", False), - ("pro=ject", False), - ("pro>ject", False), - ("pro Date: Wed, 1 Apr 2026 09:02:03 +0200 Subject: [PATCH 19/26] fix issue with mbtilesvectortiles --- Mergin/utils.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Mergin/utils.py b/Mergin/utils.py index a2f279b7..b438f996 100644 --- a/Mergin/utils.py +++ b/Mergin/utils.py @@ -162,6 +162,7 @@ "grassraster", "wms", "vectortile", + "mbtilesvectortiles", ) PACKABLE_PROVIDERS = ("ogr", "gdal", "delimitedtext", "gpx", "postgres", "memory") @@ -623,9 +624,11 @@ def datasource_filepath(layer): ds_uri = dp.dataSourceUri().split("?")[0].replace("file://", "") else: ds_uri = dp.dataSourceUri() - elif dp.name() == "vectortile": + elif dp.name() in ("vectortile", "mbtilesvectortiles"): uri = QgsProviderRegistry.instance().decodeUri("vectortile", layer.source()) ds_uri = uri["path"] if "path" in uri else None + if ds_uri and ds_uri.startswith("file://"): + ds_uri = ds_uri.replace("file://", "") else: ds_uri = None return ds_uri if os.path.isfile(ds_uri) else None @@ -696,9 +699,13 @@ def package_layer(layer, project_dir): raise PackagingError(f"Couldn't properly save layer {layer.name()}: {err}") elif layer.type() == QgsMapLayerType.VectorTileLayer: uri = QgsProviderRegistry.instance().decodeUri("vectortile", layer.source()) - is_local = os.path.isfile(uri["path"]) if "path" in uri else False - if is_local: - copy_layer_files(layer, uri["path"], project_dir) + uri_path = uri["path"] if "path" in uri else None + if uri_path: + if uri_path.startswith("file://"): + uri_path = uri_path.replace("file://", "") + is_local = os.path.isfile(uri_path) if uri_path else False + if is_local: + copy_layer_files(layer, uri_path, project_dir) elif layer.type() == QgsMapLayerType.RasterLayer: save_raster_layer(layer, project_dir) else: From b4b9baaa40905c98caf9700e9dee47d9b68ef4da Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 09:07:09 +0200 Subject: [PATCH 20/26] add versions --- .github/workflows/run-test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index e9bdf6b0..00f6dbe9 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -34,8 +34,7 @@ jobs: fail-fast: false matrix: qgis-version: - ["3.44"] - # ["3.22", "3.28", "3.30", "3.32", "3.34", "3.40", "3.42", "3.44"] + ["3.22", "3.28", "3.30", "3.32", "3.34", "3.40", "3.42", "3.44"] steps: - name: Checkout plugin code From 67867bf813aad3c52b6a8aabfcf96717f312c879 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 11:01:02 +0200 Subject: [PATCH 21/26] remove listing content --- .github/workflows/run-test.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index 00f6dbe9..a64cb7b8 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -84,10 +84,6 @@ jobs: - name: Copy client files to plugin directory run: cp -r client/mergin plugin/${{ env.PLUGIN_NAME }} - - name: List plugin directory contents - run: | - ls -R plugin/${{ env.PLUGIN_NAME }} - - name: Run tests run: conda run -n qgis_env pytest ${{ github.workspace }}/plugin/tests --cov=Mergin --cov-report=term-missing:skip-covered -rP -vv -s env: From a30ee05fbc59eadc1cf2f8de14169be4a10f638f Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 11:35:35 +0200 Subject: [PATCH 22/26] simplify --- Mergin/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mergin/utils.py b/Mergin/utils.py index b438f996..ed0ffe04 100644 --- a/Mergin/utils.py +++ b/Mergin/utils.py @@ -699,7 +699,7 @@ def package_layer(layer, project_dir): raise PackagingError(f"Couldn't properly save layer {layer.name()}: {err}") elif layer.type() == QgsMapLayerType.VectorTileLayer: uri = QgsProviderRegistry.instance().decodeUri("vectortile", layer.source()) - uri_path = uri["path"] if "path" in uri else None + uri_path = uri.get("path", None) if uri_path: if uri_path.startswith("file://"): uri_path = uri_path.replace("file://", "") From 8f9a7d46e17387dfbe92b315b7e079e979b49735 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 11:35:48 +0200 Subject: [PATCH 23/26] update --- pyproject.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 133b5a06..96faacc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,4 +1,8 @@ -[options.extras_require] +[project] +name = "Mergin" +requires-python = ">=3.9" + +[project.optional-dependencies] test = ["pytest", "pytest-cov", "pytest-qgis"] [tool.pytest.ini_options] From 5b1f4d311ff305be39c8b149d754c9d28fe70269 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 11:40:19 +0200 Subject: [PATCH 24/26] drop parameter to use pyproject.toml --- .github/workflows/code_style.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code_style.yml b/.github/workflows/code_style.yml index 923bdef3..5857e6fe 100644 --- a/.github/workflows/code_style.yml +++ b/.github/workflows/code_style.yml @@ -9,6 +9,6 @@ jobs: - uses: actions/checkout@v2 - uses: psf/black@stable with: - options: "--check --diff --verbose -l 120" + options: "--check --diff --verbose" version: 25.1.0 src: "./Mergin" \ No newline at end of file From 518ffe434ee376e06fc8ab2203e3e21cacceb97c Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 11:42:31 +0200 Subject: [PATCH 25/26] only use LTR --- .github/workflows/run-test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index a64cb7b8..c3f3feef 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -33,8 +33,7 @@ jobs: strategy: fail-fast: false matrix: - qgis-version: - ["3.22", "3.28", "3.30", "3.32", "3.34", "3.40", "3.42", "3.44"] + qgis-version: ["3.22", "3.28", "3.34", "3.40", "3.44"] steps: - name: Checkout plugin code From 8c4b4ca84a81692993c13c6ce906c156380cbd65 Mon Sep 17 00:00:00 2001 From: Jan Caha Date: Wed, 1 Apr 2026 11:45:01 +0200 Subject: [PATCH 26/26] move flake8 settings --- .github/workflows/security_check.yml | 7 ++----- pyproject.toml | 4 ++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/security_check.yml b/.github/workflows/security_check.yml index 4d781818..b7d833bd 100644 --- a/.github/workflows/security_check.yml +++ b/.github/workflows/security_check.yml @@ -19,7 +19,7 @@ jobs: run: | # Upgrade pip and install security/linting tools python -m pip install --upgrade pip - pip install bandit detect-secrets flake8 flake8-json + pip install bandit detect-secrets flake8 flake8-json flake8-pyproject - name: Run Bandit (Security Scan) # Scan the Mergin folder for vulnerabilities, excluding the test directory @@ -30,7 +30,4 @@ jobs: run: detect-secrets scan ./Mergin/ --all-files - name: Run Flake8 (Style Check) - # Style enforcement using MerginMaps standards - # Ignoring E501 (line length) and W503 (operator line breaks) - run: | - flake8 ./Mergin/ --max-line-length=120 --ignore=E501,W503 --exclude=test \ No newline at end of file + run: flake8 ./Mergin/ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 96faacc7..954f4d8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,10 @@ addopts = "-rP -vv -s" testpaths = ["tests"] pythonpath = ["."] +[tool.flake8] +max-line-length = 120 +ignore = ["E501", "W503"] + [tool.black] line-length = 120