From f63c45c7877bcd93ac19d84abe32ad3b393dfcbd Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Fri, 3 Jan 2025 08:55:16 -0800 Subject: [PATCH 01/27] Writing some initial tests for Map.py using pytest-qgis --- .gitignore | 1 + ee_plugin.py | 4 +-- pytest.ini | 2 +- requirements-dev.txt | 5 ++-- test/test_map.py | 61 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 test/test_map.py diff --git a/.gitignore b/.gitignore index ac96ab1..b389d6e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ temp venv .DS_Store htmlcov +.coverage \ No newline at end of file diff --git a/ee_plugin.py b/ee_plugin.py index 509d7e7..20583c5 100644 --- a/ee_plugin.py +++ b/ee_plugin.py @@ -17,8 +17,6 @@ from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtWidgets import QAction -from ee_plugin import provider - # read the plugin version from metadata cfg = configparser.ConfigParser() cfg.read(os.path.join(os.path.dirname(__file__), "metadata.txt")) @@ -37,6 +35,8 @@ def __init__(self, iface): application at run time. :type iface: QgsInterface """ + from ee_plugin import provider + # Save reference to the QGIS interface self.iface = iface diff --git a/pytest.ini b/pytest.ini index bfc3e7d..f44261f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,3 @@ [pytest] addopts = --cov=. --cov-report=term-missing -norecursedirs = extlibs \ No newline at end of file +norecursedirs = extlibs diff --git a/requirements-dev.txt b/requirements-dev.txt index 9011ff4..4186c0b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,6 +2,7 @@ -r requirements.txt # Include all main requirements # Development dependencies -pytest +pytest==7.4.3 # pytest-qgis does not support pytest>=8 pytest-cov -pre-commit \ No newline at end of file +pytest-qgis==2.1.0 +pre-commit diff --git a/test/test_map.py b/test/test_map.py new file mode 100644 index 0000000..054d7f6 --- /dev/null +++ b/test/test_map.py @@ -0,0 +1,61 @@ +import pytest +import ee +from qgis.core import QgsProject +import Map + + +@pytest.fixture(scope="module") +def setup_ee(): + """Initialize the Earth Engine API.""" + ee.Initialize() + + +def test_add_layer(setup_ee, qgis_app): + """Test adding a layer to the map.""" + # Create an Earth Engine Image + image = ee.Image("USGS/SRTMGL1_003") + vis_params = { + "min": 0, + "max": 4000, + "palette": ["006633", "E5FFCC", "662A00", "D8D8D8", "F5F5F5"], + } + Map.addLayer(image, vis_params, "DEM") + + # Validate if the layer was added + layers = QgsProject.instance().mapLayers() + assert len(layers) > 0, "No layers were added to the map." + + +def test_set_center(setup_ee, qgis_app): + """Test setting the map center.""" + lon, lat, zoom = -121.753, 46.855, 9 + Map.setCenter(lon, lat, zoom) + + # Verify the center and zoom + center = Map.getCenter() + assert center.getInfo()["coordinates"] == [ + lon, + lat, + ], "Center coordinates do not match." + assert round(Map.getZoom()) == zoom, "Zoom level does not match." + + +def test_get_bounds(setup_ee, qgis_app): + """Test getting the bounds of the map.""" + bounds = Map.getBounds() + assert len(bounds) == 4, "Bounds do not have the expected format." + assert all( + isinstance(coord, (float, int)) for coord in bounds + ), "Bounds coordinates are not numeric." + + +def test_get_scale(setup_ee, qgis_app): + """Test getting the map scale.""" + scale = Map.getScale() + assert scale > 0, "Scale should be a positive number." + + +def test_set_zoom(setup_ee, qgis_app): + """Test setting the zoom level.""" + Map.setZoom(10) + assert round(Map.getZoom()) == 10, "Zoom level was not set correctly." From 05e0e88fb4dcd25f4b7265fc788c0841cbef93a9 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Fri, 3 Jan 2025 10:03:32 -0800 Subject: [PATCH 02/27] Add proper registration of WMS provider --- Map.py | 2 +- ee_plugin.py | 2 +- test/test_map.py | 42 +++++++++++++++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Map.py b/Map.py index c627e06..167cbb8 100644 --- a/Map.py +++ b/Map.py @@ -27,7 +27,7 @@ def addLayer(eeObject, visParams=None, name=None, shown=True, opacity=1.0): >>> from ee_plugin import Map >>> Map.addLayer(.....) """ - from .utils import add_or_update_ee_layer + from utils import add_or_update_ee_layer add_or_update_ee_layer(eeObject, visParams, name, shown, opacity) diff --git a/ee_plugin.py b/ee_plugin.py index 20583c5..12013af 100644 --- a/ee_plugin.py +++ b/ee_plugin.py @@ -35,7 +35,7 @@ def __init__(self, iface): application at run time. :type iface: QgsInterface """ - from ee_plugin import provider + import provider # Save reference to the QGIS interface self.iface = iface diff --git a/test/test_map.py b/test/test_map.py index 054d7f6..0af8d9f 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -1,7 +1,11 @@ import pytest import ee -from qgis.core import QgsProject +from qgis.core import QgsProviderRegistry, QgsProviderMetadata +from qgis.utils import plugins +from PyQt5.QtCore import QSettings, QCoreApplication + import Map +from ee_plugin import GoogleEarthEnginePlugin @pytest.fixture(scope="module") @@ -10,20 +14,44 @@ def setup_ee(): ee.Initialize() -def test_add_layer(setup_ee, qgis_app): +@pytest.fixture(scope="module") +def load_ee_plugin(qgis_app): + """Load Earth Engine plugin and configure QSettings.""" + # Ensure WMS provider is registered + registry = QgsProviderRegistry.instance() + if "wms" not in registry.providerList(): + metadata = QgsProviderMetadata("wms", "WMS Provider", "libwmsprovider.so") + registry.registerProvider(metadata) + + # Set QSettings values required by the plugin + QCoreApplication.setOrganizationName("QGIS") + QCoreApplication.setApplicationName("QGIS Testing") + QSettings().setValue("locale/userLocale", "en") + + # Initialize and register the plugin + iface = qgis_app + plugin = GoogleEarthEnginePlugin(iface) + plugins["ee_plugin"] = plugin + plugin.check_version() + + +def test_wms_metadata(qgis_app, load_ee_plugin): + """Check WMS provider metadata.""" + registry = QgsProviderRegistry.instance() + assert "wms" in registry.providerList(), "WMS provider is not available!" + + +def test_add_layer(setup_ee, load_ee_plugin): """Test adding a layer to the map.""" - # Create an Earth Engine Image image = ee.Image("USGS/SRTMGL1_003") vis_params = { "min": 0, "max": 4000, "palette": ["006633", "E5FFCC", "662A00", "D8D8D8", "F5F5F5"], } - Map.addLayer(image, vis_params, "DEM") - # Validate if the layer was added - layers = QgsProject.instance().mapLayers() - assert len(layers) > 0, "No layers were added to the map." + # Add the layer to the map + Map.addLayer(image, vis_params, "DEM") def test_set_center(setup_ee, qgis_app): From e372fe6ecbeb5721b456fb756962736c0540ac5d Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Fri, 3 Jan 2025 11:35:09 -0800 Subject: [PATCH 03/27] wip to test add_layers functionality --- test/test_map.py | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/test/test_map.py b/test/test_map.py index 0af8d9f..06875fb 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -1,6 +1,9 @@ import pytest import ee -from qgis.core import QgsProviderRegistry, QgsProviderMetadata +from qgis.core import ( + QgsProviderRegistry, + QgsProviderMetadata, +) from qgis.utils import plugins from PyQt5.QtCore import QSettings, QCoreApplication @@ -29,8 +32,7 @@ def load_ee_plugin(qgis_app): QSettings().setValue("locale/userLocale", "en") # Initialize and register the plugin - iface = qgis_app - plugin = GoogleEarthEnginePlugin(iface) + plugin = GoogleEarthEnginePlugin(qgis_app) plugins["ee_plugin"] = plugin plugin.check_version() @@ -41,7 +43,7 @@ def test_wms_metadata(qgis_app, load_ee_plugin): assert "wms" in registry.providerList(), "WMS provider is not available!" -def test_add_layer(setup_ee, load_ee_plugin): +def test_add_layer(load_ee_plugin): """Test adding a layer to the map.""" image = ee.Image("USGS/SRTMGL1_003") vis_params = { @@ -54,21 +56,7 @@ def test_add_layer(setup_ee, load_ee_plugin): Map.addLayer(image, vis_params, "DEM") -def test_set_center(setup_ee, qgis_app): - """Test setting the map center.""" - lon, lat, zoom = -121.753, 46.855, 9 - Map.setCenter(lon, lat, zoom) - - # Verify the center and zoom - center = Map.getCenter() - assert center.getInfo()["coordinates"] == [ - lon, - lat, - ], "Center coordinates do not match." - assert round(Map.getZoom()) == zoom, "Zoom level does not match." - - -def test_get_bounds(setup_ee, qgis_app): +def test_get_bounds(): """Test getting the bounds of the map.""" bounds = Map.getBounds() assert len(bounds) == 4, "Bounds do not have the expected format." @@ -77,13 +65,7 @@ def test_get_bounds(setup_ee, qgis_app): ), "Bounds coordinates are not numeric." -def test_get_scale(setup_ee, qgis_app): +def test_get_scale(): """Test getting the map scale.""" scale = Map.getScale() assert scale > 0, "Scale should be a positive number." - - -def test_set_zoom(setup_ee, qgis_app): - """Test setting the zoom level.""" - Map.setZoom(10) - assert round(Map.getZoom()) == 10, "Zoom level was not set correctly." From 03529246056630ba34a3c5cbe98b82db5df3e90f Mon Sep 17 00:00:00 2001 From: Anthony Lukach Date: Tue, 7 Jan 2025 11:29:21 -0800 Subject: [PATCH 04/27] Add python env file to use extlibs as pythonpath --- .python.env | 1 + .vscode/settings.json | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 .python.env create mode 100644 .vscode/settings.json diff --git a/.python.env b/.python.env new file mode 100644 index 0000000..1ffaac3 --- /dev/null +++ b/.python.env @@ -0,0 +1 @@ +PYTHONPATH=${PYTHONPATH}:./extlibs diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..041b62a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.envFile": "${workspaceFolder}/.python.env" +} \ No newline at end of file From 9f2db442e39c82da0249fbf81ef8f19d712f6e64 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 7 Jan 2025 13:35:09 -0800 Subject: [PATCH 05/27] Debug adding provider (wip) --- .coverage | Bin 53248 -> 53248 bytes .python.env | 2 +- .vscode/settings.json | 9 ++++++++- Map.py | 4 ++-- provider.py | 1 + pytest.ini | 3 --- requirements-dev.txt | 1 + symbology-style.db | Bin 0 -> 86016 bytes test/test_map.py | 19 ++++++++++--------- 9 files changed, 23 insertions(+), 16 deletions(-) delete mode 100644 pytest.ini create mode 100644 symbology-style.db diff --git a/.coverage b/.coverage index c4810d5b8882ebb77d4831e7d4d8329fe589de5a..4488a1f40f99e10dbd3530b5ac69c411d0b63980 100644 GIT binary patch delta 901 zcmZXSPfSx;6vpp+@4oi+y?gILO6H$HYlP^+NMVGrAf+Z{VwG2niV;PWXdz7oC{QQC z1Zk5of<{bwUAd9fU^1g3#hnX{8>2Bo)XBIo#EoW>Q6T<{OybOWwYr(jJ@-4``QE#~ zo1320(v#Y>%Wt+3n1E3@0&TffMa>|CRes+O{y?yPQ%!wfGgr0M-k;-xLy7*r+Ktso zg_dR7&xsO#)w6;e4Ev|`vQOY0lao)&YvCAyUs;oupSL>klwK->w;ivbR zxv}j%iW&l$Yze7NLf&fKBz?A}H*k%N$N@WG9!n*D8rql~Zen@!u+0=p_S!Msq$Kk# zj?~K)o9mu}s`U=^B!&(p`cm=1?ye(oOg04`3S3!$}y1K71W}phUbz(0MWH<5cm4 zdBlAuH=%7fGuEjRl5XxMxRMKcC8-QC95}%u%H+R3ZQsME;%GEm8O?rLf2oLOE272Q za6DRUI3iQA#!s?-r%lqkw|@}a!hESkFJ1k8@7o5&W1=iEQ}Jii`5no11ZQNKdcf}&kcC+^og2-?2C=7i>G?a{(LqAKqeqb^l0pYxV;m?H2Gyn&bS q9PjE+n1{P?8*adLxB^pnPbZ<&IfTM_zA%Bi~i!mX(kris9pq7=AXi^tOH;|C%j<}I%#A4!OVPc$WP&a4J|4+_2|2Hxzk4(xB zRGaRRAPaqP2t1`4>ki;2TWmI$&AHF(a(G=XW|BA6=HuC+M0(KO>?{(58?F+5y`_JP z-QJhZ`*QK2T+?n_({E+Z#xv<`&UYb~N|t`MfOXp*3cd&2dR@( z$Q0=%8}xa7RGjVBOQS~ykSPfKQaGrz8L~9Y$3qVNaxRe^YR(k=jDPO%D;_FKh3bbT zbS@+80O8KgfGMDh$4#^8eByjOEBuhgS3ASV!ULfWWER!KpNG~dDwc{M#@*Z+W=P?U z;bUq${%fWp49Wac*u(nLgZ))7vFf0y>hRgfiS2X-o{<>2O*YarS=ATxG5Ue+f-A7s zFdHkzP4L3tsIBB* zdYxCIVWe??Z-+qe_j*P68iBFUN z$zP|dqODgK{b){RN_9ZN^YLJLsw}i2xAMyPdU3cc!4LQX XEAS4M;0-LmODK!OccE0i<#YT3-%i2O diff --git a/.python.env b/.python.env index 1ffaac3..def5263 100644 --- a/.python.env +++ b/.python.env @@ -1 +1 @@ -PYTHONPATH=${PYTHONPATH}:./extlibs +PYTHONPATH=${PYTHONPATH}:./extlibs:/Applications/QGIS-LTR.app/Contents/MacOS/lib/python3.9 diff --git a/.vscode/settings.json b/.vscode/settings.json index 041b62a..971f24a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,10 @@ { - "python.envFile": "${workspaceFolder}/.python.env" + "python.envFile": "${workspaceFolder}/.python.env", + "terminal.integrated.env.osx": { + "PYTHONPATH": "${PYTHONPATH}:./extlibs:/Applications/QGIS-LTR.app/Contents/MacOS/lib/python3.9" + }, + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": [ + "test" + ], } \ No newline at end of file diff --git a/Map.py b/Map.py index 167cbb8..1374ac8 100644 --- a/Map.py +++ b/Map.py @@ -27,9 +27,9 @@ def addLayer(eeObject, visParams=None, name=None, shown=True, opacity=1.0): >>> from ee_plugin import Map >>> Map.addLayer(.....) """ - from utils import add_or_update_ee_layer + from . import utils - add_or_update_ee_layer(eeObject, visParams, name, shown, opacity) + utils.add_or_update_ee_layer(eeObject, visParams, name, shown, opacity) def centerObject(feature, zoom=None): diff --git a/provider.py b/provider.py index 9d92705..7a6c7c3 100644 --- a/provider.py +++ b/provider.py @@ -58,6 +58,7 @@ def __init__(self, *args, **kwargs): # create WMS provider self.wms = QgsProviderRegistry.instance().createProvider("wms", *args, **kwargs) + assert self.wms, f"Failed to create WMS provider: {args}, {kwargs}" @classmethod def description(cls): diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index f44261f..0000000 --- a/pytest.ini +++ /dev/null @@ -1,3 +0,0 @@ -[pytest] -addopts = --cov=. --cov-report=term-missing -norecursedirs = extlibs diff --git a/requirements-dev.txt b/requirements-dev.txt index 4186c0b..33327aa 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,3 +6,4 @@ pytest==7.4.3 # pytest-qgis does not support pytest>=8 pytest-cov pytest-qgis==2.1.0 pre-commit +pyqt5 \ No newline at end of file diff --git a/symbology-style.db b/symbology-style.db new file mode 100644 index 0000000000000000000000000000000000000000..18c372e0ee50c9244ca4427d507d58a019667650 GIT binary patch literal 86016 zcmeI%O;6iM7{GD6r8apF1!N%>VYCMt6&0nNI8@!VwGdhgTQ+F7m8!@jhEh2sBxaSi zC*S&ID(!t$Y47`Ws%oXZtmBCtyU6M#r_nzW@pugL%=4R>gwg!^;^4w_%(LF0YkTI7 zQdLw{`N=dDMJWeA%fV0d8sE=FH^Eg+l(ULu<-yVWQsrM|Y5q^8@~ZMr`BP=H^j~>Y z+AaNEY!|;4{wh8!To-=Gf6l+keaU^yEeF5I3jqWWKmY**5J(8Lmvm!eL-iLt`_y%Y zU3=i24|>=AX=(ZCvDIi=X0!3+z%r-x_bxi-{$bPFvyRPQj`yE8j$fKTTQ9dR?XF`s zt>2qlqplkkYFCT8QLCx`nh5f)d)jk%I-Y&rwfn==-BLPO>e;>E4_b+!heu8G@Z{iN zD{3O~u=e(@Zmh4X{*Pfuw?7oo;=*DoP+XlE!*$M`%TC|++HZz$?7owX)mhMuwKdgW z6|tgFlk44dq)BadAp6vDhmPl6T%He;QS7RSvK&V7&O}1dbs-fcs?ChzIU`T}kD3he zx}qDatI=d=iwKiTH5Fh|nc053=k^8zyW3AT|65r%R#sF$Co%|!U&N@S8W(k$ZHwVf zHvFul8H6DizdK!P*98ImC~PL0RMEAVYA~w(ZmZ_W;r@#gD_#p*XZ9bx z!FY=>Sv$4uqGmi@Qx5bC#BZfkKM4dVl{~OTd8h}x*7EG{w>XTypq*N z5hhxew}Y?L`SI6kY5Z0lzwtr<0R#|0009ILKmY**5I_I{Sq1Xr#MuAKI=tkC00Iag zfB*srAb=KmY**5I_I{ z1Q0*~0R#|`Ux4#}`Nx90tg_000IagfB*srAbmAp!^>fB*srAb Date: Wed, 8 Jan 2025 11:04:58 -0800 Subject: [PATCH 06/27] Base example test implemented --- ee_plugin.py | 2 +- test/test_map.py | 21 ++++----------------- test/test_qgis_environment.py | 1 + utils.py | 4 ++-- 4 files changed, 8 insertions(+), 20 deletions(-) diff --git a/ee_plugin.py b/ee_plugin.py index 12013af..8b025ae 100644 --- a/ee_plugin.py +++ b/ee_plugin.py @@ -35,7 +35,7 @@ def __init__(self, iface): application at run time. :type iface: QgsInterface """ - import provider + from . import provider # Save reference to the QGIS interface self.iface = iface diff --git a/test/test_map.py b/test/test_map.py index 926fc6d..2e0bf99 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -1,9 +1,4 @@ import pytest -import ee -from qgis.core import ( - QgsProviderRegistry, - QgsProviderMetadata, -) from qgis.utils import plugins from PyQt5.QtCore import QSettings, QCoreApplication @@ -14,18 +9,14 @@ @pytest.fixture(scope="module", autouse=True) def setup_ee(): """Initialize the Earth Engine API.""" + import ee + ee.Initialize() @pytest.fixture(scope="module", autouse=True) def load_ee_plugin(qgis_app): """Load Earth Engine plugin and configure QSettings.""" - # Ensure WMS provider is registered - registry = QgsProviderRegistry.instance() - if "wms" not in registry.providerList(): - registry.createProvider("wms", "libwmsprovider.so") - metadata = QgsProviderMetadata("wms", "WMS Provider", "libwmsprovider.so") - registry.registerProvider(metadata) # Set QSettings values required by the plugin QCoreApplication.setOrganizationName("QGIS") @@ -38,14 +29,10 @@ def load_ee_plugin(qgis_app): plugin.check_version() -# def test_wms_metadata(): -# """Check WMS provider metadata.""" -# registry = QgsProviderRegistry.instance() -# assert "wms" in registry.providerList(), "WMS provider is not available!" - - def test_add_layer(): """Test adding a layer to the map.""" + import ee + image = ee.Image("USGS/SRTMGL1_003") vis_params = { "min": 0, diff --git a/test/test_qgis_environment.py b/test/test_qgis_environment.py index 3be9b64..3d6535d 100644 --- a/test/test_qgis_environment.py +++ b/test/test_qgis_environment.py @@ -34,6 +34,7 @@ def test_qgis_environment(self): r = QgsProviderRegistry.instance() self.assertIn("gdal", r.providerList()) self.assertIn("ogr", r.providerList()) + self.assertIn("wms", r.providerList()) # needed for our EE provider def test_projection(self): """Test that QGIS properly parses a wkt string.""" diff --git a/utils.py b/utils.py index f2298a7..1e37053 100644 --- a/utils.py +++ b/utils.py @@ -16,7 +16,7 @@ QgsRectangle, ) -import ee_plugin +from .ee_plugin import VERSION as ee_plugin_version def get_ee_image_url(image): @@ -38,7 +38,7 @@ def update_ee_layer_properties(layer, eeObject, visParams, shown, opacity): # serialize EE code ee_object = eeObject.serialize() ee_object_vis = json.dumps(visParams) - layer.setCustomProperty("ee-plugin-version", ee_plugin.ee_plugin.VERSION) + layer.setCustomProperty("ee-plugin-version", ee_plugin_version) layer.setCustomProperty("ee-object", ee_object) layer.setCustomProperty("ee-object-vis", ee_object_vis) From b89df2642b03d1a30efbf57129a036ee6c7c744d Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Wed, 8 Jan 2025 12:10:56 -0800 Subject: [PATCH 07/27] Update CI to authenticate to earthengine --- .github/workflows/ci.yml | 14 ++++++++++++++ test/test_map.py | 1 + 2 files changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6afd704..a6279f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,20 @@ jobs: run: | sudo apt update sudo apt install -y qgis python3-qgis python3-pyqt5 python3-pytest + + - name: Set Environment Variables + run: | + echo "QGIS_HOME=/usr" >> $GITHUB_ENV + echo "QT_QPA_PLATFORM=offscreen" >> $GITHUB_ENV + echo "DISPLAY=:99" >> $GITHUB_ENV + + - name: Start Virtual Display + run: Xvfb :99 -screen 0 1024x768x24 & + + - name: Configure Earth Engine Credentials + run: | + mkdir -p ~/.config/earthengine # Create the directory if it doesn't exist + echo '${{ secrets.EE_CREDENTIALS_JSON }}' > ~/.config/earthengine/credentials - name: Install dependencies run: | diff --git a/test/test_map.py b/test/test_map.py index 2e0bf99..8a270be 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -12,6 +12,7 @@ def setup_ee(): import ee ee.Initialize() + ee.Authenticate(auth_mode="localhost", quiet=True) @pytest.fixture(scope="module", autouse=True) From efd43cfba54b9fc119e38ebdfca62e55457b26f6 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Wed, 8 Jan 2025 12:33:12 -0800 Subject: [PATCH 08/27] Add test to pythonpath --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6279f4..5c7de7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,6 @@ jobs: - name: Install dependencies run: | - python3 -m pip install --upgrade pip pip install -r requirements-dev.txt - name: Run pre-commit checks @@ -45,7 +44,8 @@ jobs: - name: Run tests with coverage run: | - python -m pytest --cov=. --cov-report=html --cov-report=term-missing test/ + cd qgis_earthengine_plugin # Enter package directory + PYTHONPATH=$(pwd) python -m pytest --cov=. --cov-report=html --cov-report=term-missing test/ - name: Upload coverage report uses: actions/upload-artifact@v4 From e00ac73b8d14e046469dc21c38dc4efa5186b753 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Wed, 8 Jan 2025 13:34:17 -0800 Subject: [PATCH 09/27] Revert pytest call in CI --- .github/workflows/ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c7de7c..97055af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,8 +44,7 @@ jobs: - name: Run tests with coverage run: | - cd qgis_earthengine_plugin # Enter package directory - PYTHONPATH=$(pwd) python -m pytest --cov=. --cov-report=html --cov-report=term-missing test/ + python -m pytest --cov=. --cov-report=html --cov-report=term-missing test/ - name: Upload coverage report uses: actions/upload-artifact@v4 From a839ea9b3b5ab2f4fecb2945df4d054f86aa062a Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Wed, 8 Jan 2025 13:42:46 -0800 Subject: [PATCH 10/27] Add pythonpath --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97055af..ec5017e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,9 @@ jobs: - name: Run tests with coverage run: | - python -m pytest --cov=. --cov-report=html --cov-report=term-missing test/ + echo $(pwd) + echo $(ls .) + PYTHONPATH=$(pwd)/qgis_earthengine_plugin python -m pytest --import-mode=importlib --cov=. --cov-report=html --cov-report=term-missing test/ - name: Upload coverage report uses: actions/upload-artifact@v4 From 85d8717d870b48af33b5cc771a0cbea90df79d5d Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Mon, 13 Jan 2025 11:30:28 -0800 Subject: [PATCH 11/27] Simplify test execution in CI (wip) --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec5017e..d2461de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: - name: Configure Earth Engine Credentials run: | - mkdir -p ~/.config/earthengine # Create the directory if it doesn't exist + mkdir -p ~/.config/earthengine echo '${{ secrets.EE_CREDENTIALS_JSON }}' > ~/.config/earthengine/credentials - name: Install dependencies @@ -44,9 +44,7 @@ jobs: - name: Run tests with coverage run: | - echo $(pwd) - echo $(ls .) - PYTHONPATH=$(pwd)/qgis_earthengine_plugin python -m pytest --import-mode=importlib --cov=. --cov-report=html --cov-report=term-missing test/ + python -m pytest --cov=. --cov-report=html --cov-report=term-missing test/ - name: Upload coverage report uses: actions/upload-artifact@v4 From 99eeedbdd6e4d844f8629d3090388b1ff3045b85 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 09:46:51 -0800 Subject: [PATCH 12/27] Add future for CI dependencies --- requirements-dev.txt | 3 ++- test/test_map.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 33327aa..dcdfc55 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,4 +6,5 @@ pytest==7.4.3 # pytest-qgis does not support pytest>=8 pytest-cov pytest-qgis==2.1.0 pre-commit -pyqt5 \ No newline at end of file +pyqt5 +future \ No newline at end of file diff --git a/test/test_map.py b/test/test_map.py index 8a270be..189d1db 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -2,7 +2,7 @@ from qgis.utils import plugins from PyQt5.QtCore import QSettings, QCoreApplication -from .. import Map +import Map from ..ee_plugin import GoogleEarthEnginePlugin From d9508e88069cb084bb43da17117b729415b744e4 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 09:57:46 -0800 Subject: [PATCH 13/27] Reorganized plugin code into a module --- .coverage | Bin 53248 -> 0 bytes Map.py => qgis_earthengine_plugin/Map.py | 0 .../__init__.py | 0 .../ee_auth.py | 0 .../ee_plugin.py | 0 .../metadata.txt | 0 .../pavement.py | 0 .../provider.py | 0 utils.py => qgis_earthengine_plugin/utils.py | 0 test/test_init.py | 7 ++++++- test/test_map.py | 4 ++-- 11 files changed, 8 insertions(+), 3 deletions(-) delete mode 100644 .coverage rename Map.py => qgis_earthengine_plugin/Map.py (100%) rename __init__.py => qgis_earthengine_plugin/__init__.py (100%) rename ee_auth.py => qgis_earthengine_plugin/ee_auth.py (100%) rename ee_plugin.py => qgis_earthengine_plugin/ee_plugin.py (100%) rename metadata.txt => qgis_earthengine_plugin/metadata.txt (100%) rename pavement.py => qgis_earthengine_plugin/pavement.py (100%) rename provider.py => qgis_earthengine_plugin/provider.py (100%) rename utils.py => qgis_earthengine_plugin/utils.py (100%) diff --git a/.coverage b/.coverage deleted file mode 100644 index 4488a1f40f99e10dbd3530b5ac69c411d0b63980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53248 zcmeI5U2Ggz6@X`UW_R{yX0PqFS<=*akP>aI+FskCK$14GsolhBLX^L%6*SxN?%1Ao zcV;s)>%@^lvu#ltkn#`^52z3A0}T>wDMh@XN=1SPegsW_KnSUd;DLbD5)e>?iUjA} z+3~L9xXNy#L_}xgy?1`@J@?%2o^$Wsotf){`}bJBsn0oX#qjmbLYE+l!i261f{=iZ z2A^_I_|eM4YJw1?QR`YkP=`klI%_*&|`@>rq_7ic2_ zM1Tko0V2Q&)c31OcHKJh$&0)&{>yp1XJO^xh>x@*pvu4xxdFVJF>RT@kVKJ`RW$!0R* zX_MEx zZO`&8$JWi`X0hg*rK?tO2%&`=z-z4y$a)kj^k|T?QC16`X6CEpY$R`Fo&)7wqCu{jZ5^$d z%Z)#zH**g0YS_+@j+Fol*qDlCw`4>CtkOL09WBEbuYytY9e!MZ#xIOPpg!FlSF!^G z;_0K@P!LaH*7CjOox}>GSw6jn>EQLX?FPMMrIDZ)mCL#_$6W?<>p|myHMjaqK7?Vo z=xDmrNC=wVQfotHK?i-d?98sTHEuDU2@V2%L6~f=W*5;_Jgh^}Su|Z^-W+LM4Z4L} zZAf4`V~JRHdSETnSvG;f*z#_&zAmO@*RL0!OmH)5v{oZhR+v!Ol2_?Q!%G#@@M><@ zk$hAq8RlsAlA(_@u0VB$l~{Ii{aV#&q$`XycH(tKRziRjk`fA0f*D2!nkd+I=ht9)AF^efQm<40PdGM;Iw{D8SM zyl9l6H>nzy3oZ+Na4-Vsn6P9(Vq?~+`P_c-keertJxzTB0nOu(J)|1s$-%v$Aa84U zpyw704?7<(r_VZ0*);56NPvVh9u#GHIxl+lV6>wt!&^cb^NTsIN;sxq?|uk;Ep#i` zsZL!2eY@rz7-Kvc4K z-6hs*4Id1;mx2dldBq6TZX8Bd*v1tXn`W{P`dRpr(`p{bt_24k1|?vh7PR1OKp{-k z_==Mp#0kF0J`~`OHX=X-hyW2F0z`la5CI}U1c(3;AOb|-_9GyP5mCYUzswE`>@0hN z6=8=qB0vO)01+SpM1Tko0U|&IhyW2F0z}~22&l5u&%(zlM(>cMzRmbp!T9L--NU0} z!=s2Bc_tH-K zPVLv)8SP&6FX~HbRn4a^r(Q@slFBA8KtkGx01+SpM1Tko0U|&Ih`-$kvAr@ZC1A0xzK~~#N zz^jRCf!ErLmh0G!=AVdx$Y{GF!Tth=hq`TvO2SgR0`?kJ$T}rM z;cYv0v-K-n%CyumTy8_y$DlHij+JTY7%4zvpoSByETH9i-od5UilIxj{rL?HieO-cD=Kozg{L+xc7O|LJ?AlWpe@=l@z~r8npQ>gQ!xlC9m@V{-<0#r!|@fLvd99pYN&|H;l} zt(yNQI&y+l^Z)n(xt_a@>Ro02uT0AIXxk!N=l`*-(o)+3g86^6Bd2b*elY)+JBQmk z|Cc&frln(ufImx#b`82k0ImN=gD(*v0z`la5CI}U1c(3;AOb{y2oQnWnt&uqf`<41 zMfM*7{%9itM1Tko0U|&IhyW2F0z`la5CI}U1a3nDlB6Z@{=b&~yTJa%F0+g54fYEA zI{PxL1z^K}131Kb;Sy~`fCvx)B0vO)01+SpM1Tko0U|&I{vQbpXtJ1?(5951e*dgA z^wnpMLl<>{yMq%T26%u?&of4n>?|}5s+wZ1JGv_wWoD0IIH_V*dFw?UO zlF#(S@u0rple%zD$J4^8gS-Eo)>4rF&XoM^@4oopKevgABpmi8ee?HnB7wWG(!=)N zWE^%s7Jp~E_?o0Cm_d;*y!7f9PhZO15re}|$EGe`dU)boW>@4nD6311Kb#RZ#rvah z?VjkAl$l7tX+an6l_EkM_GDcYPNikI{0aH&FUQ~5vUlLm7t#_QOYdC#g%A-xxI7b! zz;QYvDSDRpn7C#iL}BM~MWF;&C1+3Xftj9z~-(l4TxA z5|1Jg8GZub_y2{in^OrYg$NJ>Y5g-CYfCvx)B0vO)z|A6n@BjC*XYu*}57^(>d+ZYX1A7>Y5g-CYfCvzQ8%jXxg$4Sh3s;;jGx diff --git a/Map.py b/qgis_earthengine_plugin/Map.py similarity index 100% rename from Map.py rename to qgis_earthengine_plugin/Map.py diff --git a/__init__.py b/qgis_earthengine_plugin/__init__.py similarity index 100% rename from __init__.py rename to qgis_earthengine_plugin/__init__.py diff --git a/ee_auth.py b/qgis_earthengine_plugin/ee_auth.py similarity index 100% rename from ee_auth.py rename to qgis_earthengine_plugin/ee_auth.py diff --git a/ee_plugin.py b/qgis_earthengine_plugin/ee_plugin.py similarity index 100% rename from ee_plugin.py rename to qgis_earthengine_plugin/ee_plugin.py diff --git a/metadata.txt b/qgis_earthengine_plugin/metadata.txt similarity index 100% rename from metadata.txt rename to qgis_earthengine_plugin/metadata.txt diff --git a/pavement.py b/qgis_earthengine_plugin/pavement.py similarity index 100% rename from pavement.py rename to qgis_earthengine_plugin/pavement.py diff --git a/provider.py b/qgis_earthengine_plugin/provider.py similarity index 100% rename from provider.py rename to qgis_earthengine_plugin/provider.py diff --git a/utils.py b/qgis_earthengine_plugin/utils.py similarity index 100% rename from utils.py rename to qgis_earthengine_plugin/utils.py diff --git a/test/test_init.py b/test/test_init.py index 71c65c0..7302f83 100644 --- a/test/test_init.py +++ b/test/test_init.py @@ -47,7 +47,12 @@ def test_read_init(self): ] file_path = os.path.abspath( - os.path.join(os.path.dirname(__file__), os.pardir, "metadata.txt") + os.path.join( + os.path.dirname(__file__), + os.pardir, + "qgis_earthengine_plugin", + "metadata.txt", + ) ) LOGGER.info(file_path) metadata = [] diff --git a/test/test_map.py b/test/test_map.py index 189d1db..9663dd9 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -2,8 +2,8 @@ from qgis.utils import plugins from PyQt5.QtCore import QSettings, QCoreApplication -import Map -from ..ee_plugin import GoogleEarthEnginePlugin +from qgis_earthengine_plugin import Map +from qgis_earthengine_plugin.ee_plugin import GoogleEarthEnginePlugin @pytest.fixture(scope="module", autouse=True) From 6926180777be17c4845744794b69821b8598d214 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 10:30:38 -0800 Subject: [PATCH 14/27] Add caching of dependencies and use pre-built qgis image --- .github/workflows/ci.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2461de..aa449b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,14 +11,16 @@ on: jobs: test: runs-on: ubuntu-latest + container: + image: osgeo/gdal:ubuntu-full-3.6.3 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - - name: Set up QGIS environment - run: | - sudo apt update - sudo apt install -y qgis python3-qgis python3-pyqt5 python3-pytest + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' # caching pip dependencies - name: Set Environment Variables run: | @@ -29,7 +31,7 @@ jobs: - name: Start Virtual Display run: Xvfb :99 -screen 0 1024x768x24 & - - name: Configure Earth Engine Credentials + - name: Configure Earth Engine Credentials # TODO: add secret to github run: | mkdir -p ~/.config/earthengine echo '${{ secrets.EE_CREDENTIALS_JSON }}' > ~/.config/earthengine/credentials From 84d9515dc29f7b1456527b98da709e99c57726f6 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 10:44:22 -0800 Subject: [PATCH 15/27] Activate virtualenv to avoid system wide permissions error --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa449b1..738a2cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,8 @@ jobs: - name: Set Environment Variables run: | echo "QGIS_HOME=/usr" >> $GITHUB_ENV + echo "PYTHONPATH=$QGIS_HOME/share/qgis/python" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=$QGIS_HOME/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV echo "QT_QPA_PLATFORM=offscreen" >> $GITHUB_ENV echo "DISPLAY=:99" >> $GITHUB_ENV @@ -38,6 +40,8 @@ jobs: - name: Install dependencies run: | + python -m venv venv --system-site-packages + source venv/bin/activate pip install -r requirements-dev.txt - name: Run pre-commit checks From 5bbe63c4656aadf928c110b39f7a3382b5d0f73e Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 10:48:43 -0800 Subject: [PATCH 16/27] Update python version to use matrix strategy --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 738a2cf..427a9a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,13 +13,16 @@ jobs: runs-on: ubuntu-latest container: image: osgeo/gdal:ubuntu-full-3.6.3 + strategy: + matrix: + python-version: [3.9, 3.10, 3.11] steps: - name: Checkout code uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.13' + python-version: ${{ matrix.python-version }} cache: 'pip' # caching pip dependencies - name: Set Environment Variables From 49ab5db852d1b7b4cb07641051d37124fb8678b3 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 10:51:08 -0800 Subject: [PATCH 17/27] Update python version to 3.9 --- .github/workflows/ci.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 427a9a8..bcd2dce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,16 +13,13 @@ jobs: runs-on: ubuntu-latest container: image: osgeo/gdal:ubuntu-full-3.6.3 - strategy: - matrix: - python-version: [3.9, 3.10, 3.11] steps: - name: Checkout code uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: '3.9' cache: 'pip' # caching pip dependencies - name: Set Environment Variables From 2a4572a9459fceb7145296b780dcb8a850b65836 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 10:52:37 -0800 Subject: [PATCH 18/27] Remove setup python --- .github/workflows/ci.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcd2dce..4b7e1de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,11 +16,6 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - - - uses: actions/setup-python@v5 - with: - python-version: '3.9' - cache: 'pip' # caching pip dependencies - name: Set Environment Variables run: | @@ -40,8 +35,6 @@ jobs: - name: Install dependencies run: | - python -m venv venv --system-site-packages - source venv/bin/activate pip install -r requirements-dev.txt - name: Run pre-commit checks From 05e170f20a1ffe1737551c491265007ae9862fd6 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 10:55:27 -0800 Subject: [PATCH 19/27] Update base image to Kartoza --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b7e1de..94f3847 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: test: runs-on: ubuntu-latest container: - image: osgeo/gdal:ubuntu-full-3.6.3 + image: kartoza/qgis-desktop:LTR steps: - name: Checkout code uses: actions/checkout@v4 From 60c0e0bef91f817aaf69069cc1332c7b15846197 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 11:01:07 -0800 Subject: [PATCH 20/27] Move to qgis/qgis image --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94f3847..37695ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: test: runs-on: ubuntu-latest container: - image: kartoza/qgis-desktop:LTR + image: qgis/qgis:ltr steps: - name: Checkout code uses: actions/checkout@v4 From ba319203c1d155602877b5911ee32d8f85a60d45 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 11:05:59 -0800 Subject: [PATCH 21/27] Revert to configuring our own environment --- .github/workflows/ci.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37695ac..892d854 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,24 +11,25 @@ on: jobs: test: runs-on: ubuntu-latest - container: - image: qgis/qgis:ltr steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v3 + + - name: Set up QGIS environment + run: | + sudo apt update + sudo apt install -y qgis python3-qgis python3-pyqt5 python3-pytest - name: Set Environment Variables run: | echo "QGIS_HOME=/usr" >> $GITHUB_ENV - echo "PYTHONPATH=$QGIS_HOME/share/qgis/python" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=$QGIS_HOME/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV echo "QT_QPA_PLATFORM=offscreen" >> $GITHUB_ENV echo "DISPLAY=:99" >> $GITHUB_ENV - name: Start Virtual Display run: Xvfb :99 -screen 0 1024x768x24 & - - name: Configure Earth Engine Credentials # TODO: add secret to github + - name: Configure Earth Engine Credentials run: | mkdir -p ~/.config/earthengine echo '${{ secrets.EE_CREDENTIALS_JSON }}' > ~/.config/earthengine/credentials From d17f75e5df7e844f305cc4941376f29a741e26a4 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 11:49:07 -0800 Subject: [PATCH 22/27] Move plugin files to ee_plugin module Clean up installed plugin to include only extlibs and python files. --- {qgis_earthengine_plugin => ee_plugin}/Map.py | 0 {qgis_earthengine_plugin => ee_plugin}/__init__.py | 0 {qgis_earthengine_plugin => ee_plugin}/ee_auth.py | 0 {qgis_earthengine_plugin => ee_plugin}/ee_plugin.py | 0 {qgis_earthengine_plugin => ee_plugin}/metadata.txt | 0 {qgis_earthengine_plugin => ee_plugin}/provider.py | 0 {qgis_earthengine_plugin => ee_plugin}/utils.py | 0 qgis_earthengine_plugin/pavement.py => pavement.py | 8 ++++---- test/test_map.py | 4 ++-- 9 files changed, 6 insertions(+), 6 deletions(-) rename {qgis_earthengine_plugin => ee_plugin}/Map.py (100%) rename {qgis_earthengine_plugin => ee_plugin}/__init__.py (100%) rename {qgis_earthengine_plugin => ee_plugin}/ee_auth.py (100%) rename {qgis_earthengine_plugin => ee_plugin}/ee_plugin.py (100%) rename {qgis_earthengine_plugin => ee_plugin}/metadata.txt (100%) rename {qgis_earthengine_plugin => ee_plugin}/provider.py (100%) rename {qgis_earthengine_plugin => ee_plugin}/utils.py (100%) rename qgis_earthengine_plugin/pavement.py => pavement.py (96%) diff --git a/qgis_earthengine_plugin/Map.py b/ee_plugin/Map.py similarity index 100% rename from qgis_earthengine_plugin/Map.py rename to ee_plugin/Map.py diff --git a/qgis_earthengine_plugin/__init__.py b/ee_plugin/__init__.py similarity index 100% rename from qgis_earthengine_plugin/__init__.py rename to ee_plugin/__init__.py diff --git a/qgis_earthengine_plugin/ee_auth.py b/ee_plugin/ee_auth.py similarity index 100% rename from qgis_earthengine_plugin/ee_auth.py rename to ee_plugin/ee_auth.py diff --git a/qgis_earthengine_plugin/ee_plugin.py b/ee_plugin/ee_plugin.py similarity index 100% rename from qgis_earthengine_plugin/ee_plugin.py rename to ee_plugin/ee_plugin.py diff --git a/qgis_earthengine_plugin/metadata.txt b/ee_plugin/metadata.txt similarity index 100% rename from qgis_earthengine_plugin/metadata.txt rename to ee_plugin/metadata.txt diff --git a/qgis_earthengine_plugin/provider.py b/ee_plugin/provider.py similarity index 100% rename from qgis_earthengine_plugin/provider.py rename to ee_plugin/provider.py diff --git a/qgis_earthengine_plugin/utils.py b/ee_plugin/utils.py similarity index 100% rename from qgis_earthengine_plugin/utils.py rename to ee_plugin/utils.py diff --git a/qgis_earthengine_plugin/pavement.py b/pavement.py similarity index 96% rename from qgis_earthengine_plugin/pavement.py rename to pavement.py index 4cc13c3..a86fcb1 100644 --- a/qgis_earthengine_plugin/pavement.py +++ b/pavement.py @@ -11,9 +11,9 @@ options( plugin=Bunch( name="ee_plugin", - ext_libs=path("extlibs"), - source_dir=path("."), - package_dir=path("."), + ext_libs=path(os.path.join("ee_plugin", "extlibs")), + source_dir=path("ee_plugin"), + package_dir=path("ee_plugin"), tests=["test", "tests"], excludes=[ "*.pyc", @@ -76,7 +76,7 @@ def setup(): def install(options): """install plugin to qgis""" plugin_name = options.plugin.name - src = path(__file__).dirname() + src = options.plugin.source_dir if platform.system() == "Windows": dst = ( path( diff --git a/test/test_map.py b/test/test_map.py index 9663dd9..22d78e2 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -2,8 +2,8 @@ from qgis.utils import plugins from PyQt5.QtCore import QSettings, QCoreApplication -from qgis_earthengine_plugin import Map -from qgis_earthengine_plugin.ee_plugin import GoogleEarthEnginePlugin +from ee_plugin import Map +from ee_plugin.ee_plugin import GoogleEarthEnginePlugin @pytest.fixture(scope="module", autouse=True) From 6246b5b53182b16d6cf80c38eb18f0190a7d1970 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 12:04:28 -0800 Subject: [PATCH 23/27] Modify path for paver package to avoid nested ee_plugin --- pavement.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pavement.py b/pavement.py index a86fcb1..67e47ed 100644 --- a/pavement.py +++ b/pavement.py @@ -13,7 +13,7 @@ name="ee_plugin", ext_libs=path(os.path.join("ee_plugin", "extlibs")), source_dir=path("ee_plugin"), - package_dir=path("ee_plugin"), + package_dir=path("."), tests=["test", "tests"], excludes=[ "*.pyc", @@ -149,5 +149,5 @@ def filter_excludes(files): for root, dirs, files in os.walk(src_dir): for f in filter_excludes(files): relpath = os.path.relpath(root, ".") - zipFile.write(path(root) / f, path("ee_plugin") / path(relpath) / f) + zipFile.write(path(root) / f, path(relpath) / f) filter_excludes(dirs) From 7483124f329d62add21be2cc59663ec0f88d2422 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Tue, 14 Jan 2025 12:47:14 -0800 Subject: [PATCH 24/27] Add icons, i18n, and contrib to paver packaging --- {contrib => ee_plugin/contrib}/__init__.py | 0 {contrib => ee_plugin/contrib}/palettes.py | 0 {contrib => ee_plugin/contrib}/utils.py | 0 {i18n => ee_plugin/i18n}/af.qm | Bin {i18n => ee_plugin/i18n}/af.ts | 0 {icons => ee_plugin/icons}/__init__.py | 0 {icons => ee_plugin/icons}/earth-engine.svg | 0 {icons => ee_plugin/icons}/google-cloud-project.svg | 0 {icons => ee_plugin/icons}/google-cloud.svg | 0 {icons => ee_plugin/icons}/resources.py | 0 {icons => ee_plugin/icons}/resources.qrc | 0 test/test_resources.py | 6 +++--- test/test_translations.py | 2 +- 13 files changed, 4 insertions(+), 4 deletions(-) rename {contrib => ee_plugin/contrib}/__init__.py (100%) rename {contrib => ee_plugin/contrib}/palettes.py (100%) rename {contrib => ee_plugin/contrib}/utils.py (100%) rename {i18n => ee_plugin/i18n}/af.qm (100%) rename {i18n => ee_plugin/i18n}/af.ts (100%) rename {icons => ee_plugin/icons}/__init__.py (100%) rename {icons => ee_plugin/icons}/earth-engine.svg (100%) rename {icons => ee_plugin/icons}/google-cloud-project.svg (100%) rename {icons => ee_plugin/icons}/google-cloud.svg (100%) rename {icons => ee_plugin/icons}/resources.py (100%) rename {icons => ee_plugin/icons}/resources.qrc (100%) diff --git a/contrib/__init__.py b/ee_plugin/contrib/__init__.py similarity index 100% rename from contrib/__init__.py rename to ee_plugin/contrib/__init__.py diff --git a/contrib/palettes.py b/ee_plugin/contrib/palettes.py similarity index 100% rename from contrib/palettes.py rename to ee_plugin/contrib/palettes.py diff --git a/contrib/utils.py b/ee_plugin/contrib/utils.py similarity index 100% rename from contrib/utils.py rename to ee_plugin/contrib/utils.py diff --git a/i18n/af.qm b/ee_plugin/i18n/af.qm similarity index 100% rename from i18n/af.qm rename to ee_plugin/i18n/af.qm diff --git a/i18n/af.ts b/ee_plugin/i18n/af.ts similarity index 100% rename from i18n/af.ts rename to ee_plugin/i18n/af.ts diff --git a/icons/__init__.py b/ee_plugin/icons/__init__.py similarity index 100% rename from icons/__init__.py rename to ee_plugin/icons/__init__.py diff --git a/icons/earth-engine.svg b/ee_plugin/icons/earth-engine.svg similarity index 100% rename from icons/earth-engine.svg rename to ee_plugin/icons/earth-engine.svg diff --git a/icons/google-cloud-project.svg b/ee_plugin/icons/google-cloud-project.svg similarity index 100% rename from icons/google-cloud-project.svg rename to ee_plugin/icons/google-cloud-project.svg diff --git a/icons/google-cloud.svg b/ee_plugin/icons/google-cloud.svg similarity index 100% rename from icons/google-cloud.svg rename to ee_plugin/icons/google-cloud.svg diff --git a/icons/resources.py b/ee_plugin/icons/resources.py similarity index 100% rename from icons/resources.py rename to ee_plugin/icons/resources.py diff --git a/icons/resources.qrc b/ee_plugin/icons/resources.qrc similarity index 100% rename from icons/resources.qrc rename to ee_plugin/icons/resources.qrc diff --git a/test/test_resources.py b/test/test_resources.py index d9688e9..1be071d 100644 --- a/test/test_resources.py +++ b/test/test_resources.py @@ -14,9 +14,9 @@ class GoogleEarthEngineResourcesTest(unittest.TestCase): def test_icon_png(self): """Test image paths exist""" paths = ( - "icons/google-cloud-project.svg", - "icons/google-cloud.svg", - "./icons/earth-engine.svg", + "ee_plugin/icons/google-cloud-project.svg", + "ee_plugin/icons/google-cloud.svg", + "ee_plugin/icons/earth-engine.svg", ) for path in paths: icon = QIcon(path) diff --git a/test/test_translations.py b/test/test_translations.py index 31a1358..f2d1ddc 100644 --- a/test/test_translations.py +++ b/test/test_translations.py @@ -43,7 +43,7 @@ def test_qgis_translations(self): """Test that translations work.""" parent_path = os.path.join(__file__, os.path.pardir, os.path.pardir) dir_path = os.path.abspath(parent_path) - file_path = os.path.join(dir_path, "i18n", "af.qm") + file_path = os.path.join(dir_path, "ee_plugin", "i18n", "af.qm") translator = QTranslator() translator.load(file_path) QCoreApplication.installTranslator(translator) From 2973d87f7ac3109052d0ae71b907334f8dcd139d Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Wed, 15 Jan 2025 09:39:11 -0800 Subject: [PATCH 25/27] Update path to ee_plugin module --- test/test_init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_init.py b/test/test_init.py index 7302f83..a1f4ee6 100644 --- a/test/test_init.py +++ b/test/test_init.py @@ -50,7 +50,7 @@ def test_read_init(self): os.path.join( os.path.dirname(__file__), os.pardir, - "qgis_earthengine_plugin", + "ee_plugin", "metadata.txt", ) ) From 7cb23ae254198c41fa7a11e8b01c64c67618c0e8 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Wed, 15 Jan 2025 10:58:38 -0800 Subject: [PATCH 26/27] Add paver to dev requirements --- requirements-dev.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index dcdfc55..a4cb024 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -7,4 +7,5 @@ pytest-cov pytest-qgis==2.1.0 pre-commit pyqt5 -future \ No newline at end of file +future +paver \ No newline at end of file From 82e93157cecfd7287f9550aa557553c96da97c83 Mon Sep 17 00:00:00 2001 From: Zac Deziel Date: Fri, 17 Jan 2025 08:52:47 -0800 Subject: [PATCH 27/27] Bug 195/add vector layer (#196) * Move fixtures to separate conftest.py file The goal will be to reuse the fixture for other tests * Add unit test reproducing the bud * Fix bug adding vector layers by creating layers with the EE flag * Simplify code paths layer is a QgsRasterLayer in any case --- ee_plugin/utils.py | 19 +------------------ test/conftest.py | 30 ++++++++++++++++++++++++++++++ test/test_map.py | 29 ----------------------------- test/test_vector.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 test/conftest.py create mode 100644 test/test_vector.py diff --git a/ee_plugin/utils.py b/ee_plugin/utils.py index 1e37053..4d4e33e 100644 --- a/ee_plugin/utils.py +++ b/ee_plugin/utils.py @@ -27,7 +27,6 @@ def get_ee_image_url(image): def update_ee_layer_properties(layer, eeObject, visParams, shown, opacity): layer.dataProvider().set_ee_object(eeObject) - layer.setCustomProperty("ee-layer", True) if opacity is not None: @@ -51,23 +50,7 @@ def add_ee_image_layer(image, name, shown, opacity): check_version() url = "type=xyz&url=" + get_ee_image_url(image) - - # EE raster data provider - if image.ee_type == ee.Image: - layer = QgsRasterLayer(url, name, "EE") - # EE vector data provider - if image.ee_type in [ee.Geometry, ee.Feature]: - # TODO - layer = QgsRasterLayer(url, name, "wms") - # EE raster collection data provider - if image.ee_type == ee.ImageCollection: - # TODO - layer = QgsRasterLayer(url, name, "wms") - # EE vector collection data provider - if image.ee_type == ee.FeatureCollection: - # TODO - layer = QgsRasterLayer(url, name, "wms") - + layer = QgsRasterLayer(url, name, "EE") QgsProject.instance().addMapLayer(layer) if shown is not None: diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 0000000..fccc0a5 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,30 @@ +import ee +from pytest import fixture +from qgis.utils import plugins +from PyQt5.QtCore import QSettings, QCoreApplication + +from ee_plugin.ee_plugin import GoogleEarthEnginePlugin + + +@fixture(scope="session", autouse=True) +def setup_ee(): + """Initialize the Earth Engine API.""" + print("Initializing Earth Engine API...") + ee.Initialize() + ee.Authenticate(auth_mode="localhost", quiet=True) + + +@fixture(scope="session", autouse=True) +def load_ee_plugin(qgis_app, setup_ee): + """Load Earth Engine plugin and configure QSettings.""" + + # Set QSettings values required by the plugin + QCoreApplication.setOrganizationName("QGIS") + QCoreApplication.setApplicationName("QGIS Testing") + QSettings().setValue("locale/userLocale", "en") + + # Initialize and register the plugin + plugin = GoogleEarthEnginePlugin(qgis_app) + plugins["ee_plugin"] = plugin + plugin.check_version() + yield qgis_app diff --git a/test/test_map.py b/test/test_map.py index 22d78e2..913f06f 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -1,33 +1,4 @@ -import pytest -from qgis.utils import plugins -from PyQt5.QtCore import QSettings, QCoreApplication - from ee_plugin import Map -from ee_plugin.ee_plugin import GoogleEarthEnginePlugin - - -@pytest.fixture(scope="module", autouse=True) -def setup_ee(): - """Initialize the Earth Engine API.""" - import ee - - ee.Initialize() - ee.Authenticate(auth_mode="localhost", quiet=True) - - -@pytest.fixture(scope="module", autouse=True) -def load_ee_plugin(qgis_app): - """Load Earth Engine plugin and configure QSettings.""" - - # Set QSettings values required by the plugin - QCoreApplication.setOrganizationName("QGIS") - QCoreApplication.setApplicationName("QGIS Testing") - QSettings().setValue("locale/userLocale", "en") - - # Initialize and register the plugin - plugin = GoogleEarthEnginePlugin(qgis_app) - plugins["ee_plugin"] = plugin - plugin.check_version() def test_add_layer(): diff --git a/test/test_vector.py b/test/test_vector.py new file mode 100644 index 0000000..c43ac43 --- /dev/null +++ b/test/test_vector.py @@ -0,0 +1,44 @@ +import ee +import pytest + +from ee_plugin import Map + +# initialize the Earth Engine API is required to use the ee.Geometry module +# and runs before fixtures +ee.Initialize() + +geometries = [ + (ee.Geometry.Point([1.5, 1.5]), {"color": "1eff05"}, "point"), + ( + ee.Geometry.LineString([[-35, -10], [35, -10], [35, 10], [-35, 10]]), + {"color": "FF0000"}, + "lineString", + ), + ( + ee.Geometry.LinearRing( + [[-35, -10], [35, -10], [35, 10], [-35, 10], [-35, -10]] + ), + {"color": "ee38ff"}, + "linearRing", + ), + (ee.Geometry.Rectangle([-40, -20, 40, 20]), {"color": "ffa05c"}, "rectangle"), + ( + ee.Geometry.Polygon([[[-5, 40], [65, 40], [65, 60], [-5, 60], [-5, 40]]]), + {"color": "FF0000"}, + "geodesic polygon", + ), + ( + ee.Geometry( + ee.Geometry.Polygon([[[-5, 40], [65, 40], [65, 60], [-5, 60], [-5, 40]]]), + None, + False, + ), + {"color": "000000"}, + "planar polygon", + ), +] + + +@pytest.mark.parametrize("geometry, vis_params, layer_name", geometries) +def test_add_geometry_layer(geometry, vis_params, layer_name): + Map.addLayer(geometry, vis_params, layer_name), "Layer added successfully"