Skip to content

Commit

Permalink
fix: use self.search_layer_ids again (#27)
Browse files Browse the repository at this point in the history
* fix: use self.search_layer_ids again

* test: use real identify in tests

* chore: update pytest-qgis

* chore: adjust ruff default autofix behaviour
  • Loading branch information
Joonalai authored Nov 2, 2023
1 parent 886611e commit 7f67974
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
rev: v0.0.292
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
args: [--fix, --exit-non-zero-on-fix, --extend-fixable=F401]
- repo: https://github.com/psf/black
rev: 23.7.0
hooks:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Fix defining layers to search from for set active layer tool

## [3.9.9] - 2023-11-01

- Find most logical closest feature from nested features with set active layer tool
Expand Down
5 changes: 3 additions & 2 deletions pickLayer/core/set_active_layer_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,10 @@ def set_active_layer_using_closest_feature(
def _get_identify_results(
self, location: QgsPointXY, search_layer_ids: Optional[list[str]] = None
) -> list[QgsMapToolIdentify.IdentifyResult]:
layer_ids = search_layer_ids or self.search_layer_ids or []
layers = []
if search_layer_ids:
for layer_id in search_layer_ids:
if layer_ids:
for layer_id in layer_ids:
layer = QgsProject.instance().mapLayer(layer_id)
if isinstance(layer, QgsVectorLayer):
layers.append(layer)
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ ignore = [
]
line-length = 88

unfixable = [
"F401", # Unused imports
"F841", # Unused variables
]

# List of all rules https://docs.astral.sh/ruff/rules/
select = [
"ANN", # flake8-annotations
Expand Down
2 changes: 1 addition & 1 deletion requirements-dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pytest==6.2.5
pytest-qt==3.3.0
pytest-mock==3.7.0
pytest-cov==2.12.1
pytest-qgis==1.3.1
pytest-qgis==1.3.5

#stubs
pyqt5-stubs==5.15.6.0
Expand Down
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pytest-cov==2.12.1
# via -r requirements-dev.in
pytest-mock==3.7.0
# via -r requirements-dev.in
pytest-qgis==1.3.1
pytest-qgis==1.3.5
# via -r requirements-dev.in
pytest-qt==3.3.0
# via -r requirements-dev.in
Expand Down
126 changes: 90 additions & 36 deletions test/unit/test_set_active_layer_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@
QgsPointXY,
QgsProject,
QgsRasterLayer,
QgsRectangle,
QgsVectorLayer,
QgsVectorLayerUtils,
)
from qgis.gui import QgsMapTool, QgsMapToolIdentify
from qgis.gui import QgsMapTool
from qgis_plugin_tools.tools.resources import plugin_test_data_path

from pickLayer.core.set_active_layer_tool import SetActiveLayerTool
Expand All @@ -42,11 +43,9 @@
MOUSE_LOCATION = QgsPointXY(0, 0)


def create_identify_result(
def create_identify_layers(
identified_feature_geom_wtks: list[tuple[str, str, str]]
) -> list[QgsMapToolIdentify.IdentifyResult]:
results = []

) -> None:
for wkt, crs, layer_name in identified_feature_geom_wtks:
geometry = QgsGeometry.fromWkt(wkt)
layer = QgsMemoryProviderUtils.createMemoryLayer(
Expand All @@ -57,22 +56,15 @@ def create_identify_result(
)
feature = QgsVectorLayerUtils.createFeature(layer, geometry, {})
layer.dataProvider().addFeature(feature)

# using the actual QgsMapToolIdentify.IdentifyResult causes
# fatal exceptions, mock probably is sufficient for testing
results.append(
MagicMock(**{"mLayer": layer, "mFeature": feature}) # noqa: PIE804
)

return results
QgsProject.instance().addMapLayer(layer)


@pytest.fixture()
def map_tool(qgis_iface):
def map_tool(qgis_iface, qgis_new_project):
return SetActiveLayerTool(qgis_iface.mapCanvas())


@pytest.fixture(scope="session")
@pytest.fixture()
def test_layers():
layers = [
QgsVectorLayer("PointZ", "point_layer", "memory"),
Expand Down Expand Up @@ -139,6 +131,65 @@ def test_set_active_layer_using_closest_feature(
assert len(identify_results) == expected_num_results


@pytest.mark.parametrize(
argnames=("search_layers", "expected_num_results", "search_layer_count"),
argvalues=[
([0], 2, 1),
([0, 1], 2, 1),
([0, 1], 4, 2),
([0, 1, 2], 2, 1),
([0, 1, 2], 4, 2),
([0, 1, 2], 6, 3),
],
ids=[
"2-features-from-one-layer-found",
"2-features-from-two-layers-found",
"4-features-from-two-layers-found",
"2-features-from-three-layers-found",
"4-features-from-three-layers-found",
"6-features-from-three-layers-found",
],
)
def test_set_active_layer_using_closest_feature_with_search_layer_ids(
map_tool,
test_layers,
search_layers,
expected_num_results,
search_layer_count,
mocker,
):
map_tool.search_layer_ids = [test_layers[i].id() for i in range(search_layer_count)]

layer_ids = []

for index in search_layers:
layer_ids.append(test_layers[index].id())

m_choose_layer_from_identify_results = mocker.patch.object(
map_tool,
"_choose_layer_from_identify_results",
return_value=None,
autospec=True,
)

map_tool.set_active_layer_using_closest_feature(MOUSE_LOCATION, search_radius=2.5)

identify_results = m_choose_layer_from_identify_results.call_args.args[0]
assert len(identify_results) == expected_num_results

# check that identify results are in same order
# as requested layer ids (result may contain multiple
# features from one layer)
identify_results_layer_ids = []
previous_id = ""
for result in identify_results:
if result.mLayer.id() != previous_id:
identify_results_layer_ids.append(result.mLayer.id())
previous_id = result.mLayer.id()

assert identify_results_layer_ids == layer_ids[:search_layer_count]


@pytest.mark.parametrize(
argnames=(
"search_layers",
Expand Down Expand Up @@ -283,7 +334,7 @@ def test_preferred_type_chosen_from_different_types(
mocker: MockerFixture,
qgis_iface: QgisInterface,
):
results = create_identify_result(
create_identify_layers(
[
("POINT(3 3)", "EPSG:3067", "point"),
("LINESTRING(4 4, 5 5)", "EPSG:3067", "line"),
Expand All @@ -293,8 +344,6 @@ def test_preferred_type_chosen_from_different_types(

QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3067"))

mocker.patch.object(map_tool, "identify", return_value=results)

m_set_active_layer = mocker.patch.object(
qgis_iface, "setActiveLayer", return_value=None
)
Expand All @@ -313,7 +362,7 @@ def test_closest_of_same_type_chosen(
mocker: MockerFixture,
qgis_iface: QgisInterface,
):
results = create_identify_result(
create_identify_layers(
[
("POINT(3 3)", "EPSG:3067", "point-mid"),
("POINT(2 2)", "EPSG:3067", "point-close"),
Expand All @@ -324,8 +373,6 @@ def test_closest_of_same_type_chosen(
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3067"))
map_tool.canvas().setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:3067"))

mocker.patch.object(map_tool, "identify", return_value=results)

m_set_active_layer = mocker.patch.object(
qgis_iface, "setActiveLayer", return_value=None
)
Expand All @@ -345,19 +392,32 @@ def test_closest_of_same_type_chosen_even_if_project_and_layer_crs_differs(
qgis_iface: QgisInterface,
qgis_new_project,
):
results = create_identify_result(
Settings.search_radius.set(2)
create_identify_layers(
[
# points close to 250000,6700000 in 3067 in different crs's
("POINT(22.46220271 60.35440884)", "EPSG:4326", "point-far"),
("POINT(2415468 6694753)", "EPSG:2392", "point-mid"),
("POINT(2501177 8479351)", "EPSG:3857", "point-close"),
(
"POINT(22.46220271 60.35440884)",
"EPSG:4326",
"point-far",
),
(
"POINT(2415468 6694753)",
"EPSG:2392",
"point-mid",
),
(
"POINT(2501177 8479351)",
"EPSG:3857",
"point-close",
),
]
)

QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3067"))
map_tool.canvas().setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:3067"))

mocker.patch.object(map_tool, "identify", return_value=results)
map_tool.canvas().setExtent(QgsRectangle(249900, 6699000, 250100, 6701000))
map_tool.canvas().refreshAllLayers()

m_set_active_layer = mocker.patch.object(
qgis_iface, "setActiveLayer", return_value=None
Expand All @@ -378,7 +438,7 @@ def test_line_crossing_origin_chosen_as_closest(
qgis_iface: QgisInterface,
qgis_new_project,
):
results = create_identify_result(
create_identify_layers(
[
("LINESTRING(1.1 1.1, 2 2)", "EPSG:3067", "line-not-crossing"),
("LINESTRING(0 2, 2 0)", "EPSG:3067", "line-crossing"),
Expand All @@ -388,8 +448,6 @@ def test_line_crossing_origin_chosen_as_closest(
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3067"))
map_tool.canvas().setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:3067"))

mocker.patch.object(map_tool, "identify", return_value=results)

m_set_active_layer = mocker.patch.object(
qgis_iface, "setActiveLayer", return_value=None
)
Expand All @@ -409,7 +467,7 @@ def test_top_polygon_chosen_from_multiple_nested_even_if_top_not_closest(
qgis_iface: QgisInterface,
qgis_new_project,
):
results = create_identify_result(
create_identify_layers(
[
("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", "EPSG:3067", "polygon-0-10"),
("POLYGON((0 -5, 0 5, 5 5, 5 -5, 0 -5))", "EPSG:3067", "polygon-5-5"),
Expand All @@ -419,8 +477,6 @@ def test_top_polygon_chosen_from_multiple_nested_even_if_top_not_closest(
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3067"))
map_tool.canvas().setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:3067"))

mocker.patch.object(map_tool, "identify", return_value=results)

m_set_active_layer = mocker.patch.object(
qgis_iface, "setActiveLayer", return_value=None
)
Expand All @@ -441,7 +497,7 @@ def test_bottom_polygon_chosen_from_multiple_nested_when_bottom_closest(
qgis_iface: QgisInterface,
qgis_new_project,
):
results = create_identify_result(
create_identify_layers(
[
("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", "EPSG:3067", "polygon-0-10"),
("POLYGON((3 3, 3 5, 5 5, 5 3, 3 3))", "EPSG:3067", "polygon-3-5"),
Expand All @@ -451,8 +507,6 @@ def test_bottom_polygon_chosen_from_multiple_nested_when_bottom_closest(
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem("EPSG:3067"))
map_tool.canvas().setDestinationCrs(QgsCoordinateReferenceSystem("EPSG:3067"))

mocker.patch.object(map_tool, "identify", return_value=results)

m_set_active_layer = mocker.patch.object(
qgis_iface, "setActiveLayer", return_value=None
)
Expand Down

0 comments on commit 7f67974

Please sign in to comment.