Skip to content

Commit

Permalink
Fix sample feature expression [GeoCat/qgis-bridge-plugin#189], fix re…
Browse files Browse the repository at this point in the history
…gex char escape warning
  • Loading branch information
GeoSander committed Oct 8, 2024
1 parent 3e96c6e commit 76da280
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
34 changes: 25 additions & 9 deletions bridgestyle/qgis/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from qgis.core import (
QgsExpressionNode, QgsExpression, QgsExpressionNodeBinaryOperator,
QgsMapLayer, QgsVectorLayer, QgsFeatureRequest, QgsExpressionContext,
QgsExpressionContextUtils, QgsFields
QgsExpressionContextUtils, QgsFields, QgsFeature
)
except (ImportError, ModuleNotFoundError):
QgsExpressionNodeBinaryOperator = None
Expand Down Expand Up @@ -150,18 +150,13 @@ def __init__(self, layer: QgsMapLayer):

self.layer = layer

if not isinstance(layer, QgsVectorLayer):
# Can't sample features from non-vector layers
return

feature = next(layer.getFeatures(QgsFeatureRequest().setFilterFid(0)))
feature = self._get_feature(layer)
if feature is None:
# Empty layer: can't get a feature
self.warnings.add(f"Layer '{layer.name()}' contains no features")
# Not a vector layer or no features found
return

# Get fields
self.fields = layer.fields()
self.fields = feature.fields()

# Set context to the first feature
try:
Expand All @@ -172,6 +167,27 @@ def __init__(self, layer: QgsMapLayer):
except Exception as e:
self.warnings.add(f"Can't get expression context for layer '{layer.name()}': {str(e)}")

def _get_feature(self, layer: QgsMapLayer) -> Optional[QgsFeature]:
""" Returns the first feature of the given vector layer, or None if there aren't any. """
if not isinstance(layer, QgsVectorLayer):
# Can't sample features from non-vector layers
return None

try:
feature = None
for ft in layer.getFeatures(QgsFeatureRequest().setLimit(10)):
# Sample 10 features and use the first valid one
if ft and ft.isValid():
feature = ft
break
if not feature:
raise ValueError("no valid feature found")
except Exception as e:
self.warnings.add(f"Can't get sample feature for layer '{layer.name()}': {str(e)}")
return None

return feature

def __del__(self):
""" Cleans up the expression converter instance. """
self.layer = None
Expand Down
6 changes: 4 additions & 2 deletions bridgestyle/sld/fromgeostyler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
import re
from re import compile
from xml.dom import minidom
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement
Expand All @@ -14,6 +14,8 @@
from ..version import __version__
from ..geostyler.custom_properties import WellKnownText

REGEX_NONWORDCHARS = compile(r'\W')

_warnings = []


Expand Down Expand Up @@ -87,7 +89,7 @@ def _replaceSpecialCharacters(replacement, text=""):
"""
Replace all characters that are not matching one of [a-zA-Z0-9_].
"""
return re.sub('[^\w]', replacement, text)
return REGEX_NONWORDCHARS.sub(replacement, text)


def _createSymbolizers(symbolizers) -> list:
Expand Down

0 comments on commit 76da280

Please sign in to comment.