From e3a084be43362a5c8ab2011ffb28fe4bfaf9ad0b Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Sat, 18 Oct 2025 05:43:58 -0400 Subject: [PATCH] WMS 1.3.0: support any boolean for queryable layers (#993) --- owslib/map/wms130.py | 6 ++++-- owslib/util.py | 45 ++++++++++++++++++++++++++++++++------------ tests/test_util.py | 21 +++++++++++++++++++-- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/owslib/map/wms130.py b/owslib/map/wms130.py index e1e40530..11c9a3ff 100644 --- a/owslib/map/wms130.py +++ b/owslib/map/wms130.py @@ -2,9 +2,11 @@ # ============================================================================= # Copyright (c) 2004, 2006 Sean C. Gillies # Copyright (c) 2005 Nuxeo SARL +# Copyright (c) 2025 Tom Kralidis # # Authors : Sean Gillies # Julien Anguenot +# Tom Kralidis # # Contact email: sgillies@frii.com # ============================================================================= @@ -20,7 +22,7 @@ from owslib.etree import etree from owslib.util import (openURL, ServiceException, testXMLValue, extract_xml_list, xmltag_split, OrderedDict, nspath, - nspath_eval, bind_url, Authentication) + nspath_eval, bind_url, Authentication, str2bool) from owslib.fgdc import Metadata from owslib.iso import MD_Metadata from owslib.iso3 import MD_Metadata as MD_Metadata3 # ISO 19115 Part 3 XML @@ -446,7 +448,7 @@ def __init__(self, elem, parent=None, children=None, index=0, parse_remote_metad self.id = self.name = testXMLValue(elem.find(nspath('Name', WMS_NAMESPACE))) # layer attributes - self.queryable = int(elem.attrib.get('queryable', 0)) + self.queryable = int(str2bool(elem.attrib.get('queryable'), '0')) self.cascaded = int(elem.attrib.get('cascaded', 0)) self.opaque = int(elem.attrib.get('opaque', 0)) self.noSubsets = int(elem.attrib.get('noSubsets', 0)) diff --git a/owslib/util.py b/owslib/util.py index 8aefd079..4eb33495 100644 --- a/owslib/util.py +++ b/owslib/util.py @@ -1,30 +1,31 @@ # -*- coding: ISO-8859-15 -*- # ============================================================================= -# Copyright (c) 2024 Tom Kralidis +# Copyright (c) 2025 Tom Kralidis # # Authors : Tom Kralidis # # Contact email: tomkralidis@gmail.com # ============================================================================= -import os -import sys +import codecs from collections import OrderedDict -from dateutil import parser -from datetime import datetime, timedelta, timezone -from owslib.etree import etree, ParseError -from owslib.namespaces import Namespaces -from urllib.parse import urlsplit, urlencode, urlparse, parse_qs, urlunparse, parse_qsl import copy - +from copy import deepcopy +from datetime import datetime, timedelta, timezone from io import StringIO, BytesIO - +import os import re -from copy import deepcopy +import sys +from typing import Union +from urllib.parse import urlsplit, urlencode, urlparse, parse_qs, urlunparse, parse_qsl import warnings + +from dateutil import parser import requests from requests.auth import AuthBase -import codecs + +from owslib.etree import etree, ParseError +from owslib.namespaces import Namespaces """ Utility functions and classes @@ -1047,3 +1048,23 @@ def __repr__(self, *args, **kwargs): return '<{} shared={} username={} password={} cert={} verify={} auth_delegate={}>'.format( self.__class__.__name__, self.shared, self.username, self.password, self.cert, self.verify, self.auth_delegate) + + +def str2bool(value: Union[bool, str]) -> bool: + """ + helper function to return Python boolean + type (source: https://stackoverflow.com/a/715468) + + :param value: value to be evaluated + + :returns: `bool` of whether the value is boolean-ish + """ + + value2 = False + + if isinstance(value, bool): + value2 = value + else: + value2 = value.lower() in ('yes', 'true', 't', '1', 'on') + + return value2 diff --git a/tests/test_util.py b/tests/test_util.py index 4db76189..386a0921 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,10 +1,20 @@ # -*- coding: UTF-8 -*- +# ============================================================================= +# Copyright (c) 2025 Tom Kralidis +# +# Authors : Tom Kralidis +# +# Contact email: tomkralidis@gmail.com +# ============================================================================= + + import codecs +from datetime import datetime, timezone from unittest import mock + import pytest -from owslib.util import clean_ows_url, build_get_url, strip_bom, extract_time, ResponseWrapper, getXMLTree from owslib.etree import etree -from datetime import datetime, timezone +from owslib.util import clean_ows_url, build_get_url, strip_bom, extract_time, ResponseWrapper, getXMLTree, str2bool def test_strip_bom(): @@ -127,3 +137,10 @@ def test_extract_time(): assert start.isoformat()[-6:] == "+00:00" stop = extract_time(etree.fromstring(indefinite_sample)) assert stop.isoformat()[-6:] == "+00:00" + + +def test_str2bool(): + assert str2bool('1') + assert not str2bool('0') + assert int(str2bool('true')) == 1 + assert int(str2bool('false')) == 0