diff --git a/owslib/feature/wfs100.py b/owslib/feature/wfs100.py index a253f926..7baba92d 100644 --- a/owslib/feature/wfs100.py +++ b/owslib/feature/wfs100.py @@ -471,9 +471,7 @@ def parse_remote_metadata(self, timeout=30): if mdelem is not None: metadataUrl["metadata"] = MD_Metadata(mdelem) else: - mdelem = doc.find( - ".//" + util.nspath_eval("mdb:MD_Metadata", n.get_namespaces(["mdb"])) - ) + mdelem = MD_Metadata_3.find_start(doc) if mdelem is not None: metadataUrl["metadata"] = MD_Metadata_3(mdelem) else: diff --git a/owslib/feature/wfs110.py b/owslib/feature/wfs110.py index c58decc4..268467d4 100644 --- a/owslib/feature/wfs110.py +++ b/owslib/feature/wfs110.py @@ -13,12 +13,12 @@ testXMLValue, nspath_eval, ServiceException, - Authentication, - # openURL, + Authentication ) from owslib.etree import etree from owslib.fgdc import Metadata from owslib.iso import MD_Metadata +from owslib.iso_3 import MD_Metadata as MD_Metadata_3 # ISO 19115 Part 3 XML from owslib.ows import ( OwsCommon, ServiceIdentification, @@ -488,6 +488,10 @@ def parse_remote_metadata(self, timeout=30): if mdelem is not None: metadataUrl["metadata"] = MD_Metadata(mdelem) else: - metadataUrl["metadata"] = None + mdelem = MD_Metadata_3.find_start(doc) + if mdelem is not None: + metadataUrl["metadata"] = MD_Metadata_3(mdelem) + else: + metadataUrl["metadata"] = None except Exception: metadataUrl["metadata"] = None diff --git a/owslib/feature/wfs200.py b/owslib/feature/wfs200.py index a6b07657..330dd6df 100644 --- a/owslib/feature/wfs200.py +++ b/owslib/feature/wfs200.py @@ -10,7 +10,7 @@ from owslib import util from owslib.fgdc import Metadata from owslib.iso import MD_Metadata -from owslib.iso_3 import MD_Metadata as MD_Metadata_3 +from owslib.iso_3 import MD_Metadata as MD_Metadata_3 # ISO 19115 Part 3 XML from owslib.ows import Constraint, ServiceIdentification, ServiceProvider, OperationsMetadata from owslib.etree import etree from owslib.util import nspath, testXMLValue, openURL, Authentication @@ -613,11 +613,11 @@ def parse_remote_metadata(self, timeout=30): metadataUrl["metadata"] = MD_Metadata(mdelem) continue else: # ISO 19115 Part 3 XML - mdelem = doc.find( - ".//" + util.nspath_eval("mdb:MD_Metadata", n.get_namespaces(["mdb"])) - ) + mdelem = MD_Metadata_3.find_start(doc) if mdelem is not None: metadataUrl["metadata"] = MD_Metadata_3(mdelem) + else: + metadataUrl["metadata"] = None continue except Exception: metadataUrl["metadata"] = None diff --git a/owslib/iso_3.py b/owslib/iso_3.py index c4f0185a..9c03bac5 100755 --- a/owslib/iso_3.py +++ b/owslib/iso_3.py @@ -255,6 +255,20 @@ def __init__(self, md=None): else: self.dataquality = None + @staticmethod + def find_start(doc): + """ Tests for valid ISO 19115 Part 3 XML and returns the starting tag + + :param doc: lxml Element object + :returns: 'mdb:MD_Metadata' lxml Element object + """ + mtags = doc.xpath("//mdb:MD_Metadata", namespaces=NAMESPACES_V2) + if len(mtags) > 0: + return mtags[0] + mtags = doc.xpath("//mdb:MD_Metadata", namespaces=NAMESPACES_V1) + if len(mtags) > 0: + return mtags[0] + return None def get_all_contacts(self): """ Get all contacts in identification part of document diff --git a/owslib/map/wms111.py b/owslib/map/wms111.py index a62a4dcc..f1ed3144 100644 --- a/owslib/map/wms111.py +++ b/owslib/map/wms111.py @@ -25,7 +25,7 @@ bind_url, nspath_eval, Authentication) from owslib.fgdc import Metadata from owslib.iso import MD_Metadata -from owslib.iso_3 import MD_Metadata_3 +from owslib.iso_3 import MD_Metadata as MD_Metadata_3 # ISO 19115 Part 3 XML from owslib.map.common import WMSCapabilitiesReader, AbstractContentMetadata from owslib.namespaces import Namespaces @@ -619,11 +619,11 @@ def parse_remote_metadata(self, timeout=30): metadataUrl['metadata'] = MD_Metadata(mdelem) continue else: # ISO 19115 Part 3 XML - mdelem = doc.find( - ".//" + nspath_eval("mdb:MD_Metadata", n.get_namespaces(["mdb"])) - ) + mdelem = MD_Metadata_3.find_start(doc) if mdelem is not None: metadataUrl["metadata"] = MD_Metadata_3(mdelem) + else: + metadataUrl["metadata"] = None continue except Exception: metadataUrl['metadata'] = None diff --git a/owslib/map/wms130.py b/owslib/map/wms130.py index 44dc484c..c787dc92 100644 --- a/owslib/map/wms130.py +++ b/owslib/map/wms130.py @@ -23,7 +23,7 @@ nspath_eval, bind_url, Authentication) from owslib.fgdc import Metadata from owslib.iso import MD_Metadata -from owslib.iso_3 import MD_Metadata_3 +from owslib.iso_3 import MD_Metadata as MD_Metadata_3 # ISO 19115 Part 3 XML from owslib.crs import Crs from owslib.namespaces import Namespaces from owslib.map.common import WMSCapabilitiesReader, AbstractContentMetadata @@ -711,9 +711,7 @@ def parse_remote_metadata(self, timeout=30): metadataUrl['metadata'] = MD_Metadata(mdelem) continue else: - mdelem = doc.find( - ".//" + nspath_eval("mdb:MD_Metadata", n.get_namespaces(["mdb"])) - ) + mdelem = MD_Metadata_3.find_start(doc) if mdelem is not None: metadataUrl["metadata"] = MD_Metadata_3(mdelem) else: diff --git a/tests/test_iso3_parsing.py b/tests/test_iso3_parsing.py index 88c9e1c6..05fdc027 100644 --- a/tests/test_iso3_parsing.py +++ b/tests/test_iso3_parsing.py @@ -592,6 +592,8 @@ def test_service2(emd): assert(srv_ident.fees == "Resource > Service Details > Access Properties > Fees") def test_md_distribution(emd): + """ Test MD_Distribution + """ contact = emd.distribution.distributor[0].contact assert contact.address =='Resource > Distribution > Distributor > Contact Information > Address' assert contact.city =='Resource > Distribution > Distributor > Contact Information > City' diff --git a/tests/test_remote_metadata.py b/tests/test_remote_metadata.py index 92c93441..2cecc94b 100644 --- a/tests/test_remote_metadata.py +++ b/tests/test_remote_metadata.py @@ -203,18 +203,18 @@ def read(*args, **kwargs): monkeypatch.setattr( owslib.map.common.WMSCapabilitiesReader, 'read', read) +def openURL(*args, **kwargs): + """ Used to patch the 'openURL' call, returning ISO 19139 XML + """ + print("@patch openURL") + return open('tests/resources/csw_dov_getrecordbyid.xml', 'rb') -@pytest.fixture -def mp_remote_md(monkeypatch): - def openURL(*args, **kwargs): - with open('tests/resources/csw_dov_getrecordbyid.xml', 'r') as f: - data = f.read() - if type(data) is not bytes: - data = data.encode('utf-8') - data = etree.fromstring(data) - return data - monkeypatch.setattr(owslib.util, 'openURL', openURL) +def openURL_3(*args, **kwargs): + """ Used to patch the 'openURL' call, returning ISO 19115 Part 3 XML + """ + print("@patch openURL_3") + return open('tests/resources/iso3_examples/auscope-3d-model.xml', 'rb') class TestOffline(object): @@ -314,7 +314,11 @@ def test_wfs_110_noremotemd_parse_all(self, mp_wfs_110_nometadata): assert type(mdrecords) is list assert len(mdrecords) == 0 - def test_wfs_110_noremotemd_parse_single(self, mp_wfs_110_nometadata): + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wfs_110_noremotemd_parse_single(self, mp_wfs_110_nometadata, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WFS 1.1.0. Tests parsing the remote metadata for a single layer. @@ -328,6 +332,9 @@ def test_wfs_110_noremotemd_parse_single(self, mp_wfs_110_nometadata): Monkeypatch the call to the remote GetCapabilities request. """ + import owslib.feature.wfs110 + monkeypatch.setattr(owslib.feature.wfs110, 'openURL', openURL_in) + wfs = WebFeatureService(url='http://localhost/not_applicable', version='1.1.0', parse_remote_metadata=False) @@ -339,6 +346,9 @@ def test_wfs_110_noremotemd_parse_single(self, mp_wfs_110_nometadata): assert type(mdrecords) is list assert len(mdrecords) == 0 + for m in mdrecords: + assert type(m) is lib_in + def test_wfs_110_noremotemd_parse_none(self, mp_wfs_110_nometadata): """Test the remote metadata parsing for WFS 1.1.0. @@ -362,7 +372,12 @@ def test_wfs_110_noremotemd_parse_none(self, mp_wfs_110_nometadata): assert type(mdrecords) is list assert len(mdrecords) == 0 - def test_wfs_110_remotemd_parse_all(self, mp_wfs_110, mp_remote_md): + + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wfs_110_remotemd_parse_all(self, mp_wfs_110, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WFS 1.1.0. Tests parsing the remote metadata for all layers. @@ -374,10 +389,13 @@ def test_wfs_110_remotemd_parse_all(self, mp_wfs_110, mp_remote_md): ---------- mp_wfs_110 : pytest.fixture Monkeypatch the call to the remote GetCapabilities request. - mp_remote_md : pytest.fixture - Monkeypatch the call to the remote metadata. + monkeypatch : pytest.fixture + patch the call to the remote openURL. """ + import owslib.feature.wfs110 + monkeypatch.setattr(owslib.feature.wfs110, 'openURL', openURL_in) + wfs = WebFeatureService(url='http://localhost/not_applicable', version='1.1.0', parse_remote_metadata=True) @@ -389,9 +407,13 @@ def test_wfs_110_remotemd_parse_all(self, mp_wfs_110, mp_remote_md): assert len(mdrecords) == 1 for m in mdrecords: - assert type(m) is owslib.iso.MD_Metadata + assert type(m) is lib_in - def test_wfs_110_remotemd_parse_single(self, mp_wfs_110, mp_remote_md): + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wfs_110_remotemd_parse_single(self, mp_wfs_110, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WFS 1.1.0. Tests parsing the remote metadata for a single layer. @@ -403,10 +425,13 @@ def test_wfs_110_remotemd_parse_single(self, mp_wfs_110, mp_remote_md): ---------- mp_wfs_110 : pytest.fixture Monkeypatch the call to the remote GetCapabilities request. - mp_remote_md : pytest.fixture - Monkeypatch the call to the remote metadata. + monkeypatch : pytest.fixture + patch the call to the remote openURL. """ + import owslib.feature.wfs110 + monkeypatch.setattr(owslib.feature.wfs110, 'openURL', openURL_in) + wfs = WebFeatureService(url='http://localhost/not_applicable', version='1.1.0', parse_remote_metadata=False) @@ -419,7 +444,7 @@ def test_wfs_110_remotemd_parse_single(self, mp_wfs_110, mp_remote_md): assert len(mdrecords) == 1 for m in mdrecords: - assert type(m) is owslib.iso.MD_Metadata + assert type(m) is lib_in def test_wfs_110_remotemd_parse_none(self, mp_wfs_110): """Test the remote metadata parsing for WFS 1.1.0. @@ -516,7 +541,12 @@ def test_wfs_200_noremotemd_parse_none(self, mp_wfs_200_nometadata): assert type(mdrecords) is list assert len(mdrecords) == 0 - def test_wfs_200_remotemd_parse_all(self, mp_wfs_200, mp_remote_md): + + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wfs_200_remotemd_parse_all(self, mp_wfs_200, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WFS 2.0.0. Tests parsing the remote metadata for all layers. @@ -528,10 +558,13 @@ def test_wfs_200_remotemd_parse_all(self, mp_wfs_200, mp_remote_md): ---------- mp_wfs_200 : pytest.fixture Monkeypatch the call to the remote GetCapabilities request. - mp_remote_md : pytest.fixture - Monkeypatch the call to the remote metadata. + monkeypatch : pytest.fixture + patch the call to the remote openURL. """ + import owslib.feature.wfs200 + monkeypatch.setattr(owslib.feature.wfs200, 'openURL', openURL_in) + wfs = WebFeatureService(url='http://localhost/not_applicable', version='2.0.0', parse_remote_metadata=True) @@ -540,12 +573,17 @@ def test_wfs_200_remotemd_parse_all(self, mp_wfs_200, mp_remote_md): mdrecords = layer.get_metadata() assert type(mdrecords) is list - assert len(mdrecords) == 1 + assert len(mdrecords) == 2 for m in mdrecords: - assert type(m) is owslib.iso.MD_Metadata + assert type(m) is lib_in + - def test_wfs_200_remotemd_parse_single(self, mp_wfs_200, mp_remote_md): + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wfs_200_remotemd_parse_single(self, mp_wfs_200, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WFS 2.0.0. Tests parsing the remote metadata for a single layer. @@ -557,10 +595,13 @@ def test_wfs_200_remotemd_parse_single(self, mp_wfs_200, mp_remote_md): ---------- mp_wfs_200 : pytest.fixture Monkeypatch the call to the remote GetCapabilities request. - mp_remote_md : pytest.fixture - Monkeypatch the call to the remote metadata. + monkeypatch : pytest.fixture + patch the call to the remote openURL. """ + import owslib.feature.wfs200 + monkeypatch.setattr(owslib.feature.wfs200, 'openURL', openURL_in) + wfs = WebFeatureService(url='http://localhost/not_applicable', version='2.0.0', parse_remote_metadata=False) @@ -570,10 +611,10 @@ def test_wfs_200_remotemd_parse_single(self, mp_wfs_200, mp_remote_md): mdrecords = layer.get_metadata() assert type(mdrecords) is list - assert len(mdrecords) == 1 + assert len(mdrecords) == 2 for m in mdrecords: - assert type(m) is owslib.iso.MD_Metadata + assert type(m) is lib_in def test_wfs_200_remotemd_parse_none(self, mp_wfs_200): """Test the remote metadata parsing for WFS 2.0.0. @@ -670,7 +711,11 @@ def test_wms_111_noremotemd_parse_none(self, mp_wms_111_nometadata): assert type(mdrecords) is list assert len(mdrecords) == 0 - def test_wms_130_remotemd_parse_all(self, mp_wms_130): + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wms_130_remotemd_parse_all(self, mp_wms_130, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WMS 1.3.0. Tests parsing the remote metadata for all layers. @@ -682,8 +727,13 @@ def test_wms_130_remotemd_parse_all(self, mp_wms_130): ---------- mp_wms_130 : pytest.fixture Monkeypatch the call to the remote GetCapabilities request. + monkeypatch : pytest.fixture + patch the call to the remote openURL. """ + import owslib.map.wms130 + monkeypatch.setattr(owslib.map.wms130, 'openURL', openURL_in) + wms = WebMapService(url='http://localhost/not_applicable', version='1.3.0', parse_remote_metadata=True) @@ -695,9 +745,13 @@ def test_wms_130_remotemd_parse_all(self, mp_wms_130): assert len(mdrecords) == 1 for m in mdrecords: - assert type(m) is owslib.iso.MD_Metadata + assert type(m) is lib_in - def test_wms_130_remotemd_parse_single(self, mp_wms_130): + @pytest.mark.parametrize("openURL_in, lib_in", [ + (openURL, owslib.iso.MD_Metadata), + (openURL_3, owslib.iso_3.MD_Metadata), + ]) + def test_wms_130_remotemd_parse_single(self, mp_wms_130, monkeypatch, openURL_in, lib_in): """Test the remote metadata parsing for WMS 1.3.0. Tests parsing the remote metadata for a single layer. @@ -709,8 +763,13 @@ def test_wms_130_remotemd_parse_single(self, mp_wms_130): ---------- mp_wms_130 : pytest.fixture Monkeypatch the call to the remote GetCapabilities request. + monkeypatch : pytest.fixture + patch the call to the remote openURL. """ + import owslib.map.wms130 + monkeypatch.setattr(owslib.map.wms130, 'openURL', openURL_in) + wms = WebMapService(url='http://localhost/not_applicable', version='1.3.0', parse_remote_metadata=False) @@ -723,7 +782,7 @@ def test_wms_130_remotemd_parse_single(self, mp_wms_130): assert len(mdrecords) == 1 for m in mdrecords: - assert type(m) is owslib.iso.MD_Metadata + assert type(m) is lib_in def test_wms_130_remotemd_parse_none(self, mp_wms_130): """Test the remote metadata parsing for WMS 1.3.0. diff --git a/tests/test_remote_metadata_iso3.py b/tests/test_remote_metadata_iso3.py new file mode 100644 index 00000000..078a4324 --- /dev/null +++ b/tests/test_remote_metadata_iso3.py @@ -0,0 +1,71 @@ +import pytest + +import owslib +import owslib.util +from owslib.etree import etree +from owslib.wfs import WebFeatureService +from owslib.wms import WebMapService + + +@pytest.fixture +def mp_wfs_110(monkeypatch): + """Monkeypatch the call to the remote GetCapabilities request of WFS + version 1.1.0. + + Parameters + ---------- + monkeypatch : pytest.fixture + PyTest monkeypatch fixture. + + """ + def read(*args, **kwargs): + with open('tests/resources/wfs_dov_getcapabilities_110.xml', 'r') as f: + data = f.read() + if type(data) is not bytes: + data = data.encode('utf-8') + data = etree.fromstring(data) + return data + + monkeypatch.setattr( + owslib.feature.common.WFSCapabilitiesReader, 'read', read) + +@pytest.fixture +def mp_md3(monkeypatch): + """ Patch in ISO 19115 Part 3 XML + """ + def openURL(*args, **kwargs): + data = open('tests/resources/iso3_examples/auscope-3d-model.xml', 'rb') + return data + + monkeypatch.setattr(owslib.util, "openURL", openURL) + +class TestOffline(object): + + def test_wfs_110_remotemd3_parse_all(self, mp_md3, mp_wfs_110): + """Test the remote metadata parsing for WFS 1.1.0. + + Tests parsing the remote metadata for all layers. + + Test whether the method is available and returns remote metadata + if MetadataURLs are available in the GetCapabilities. + + Parameters + ---------- + mp_wfs_110 : pytest.fixture + Monkeypatch the call to the remote GetCapabilities request. + mp_md3 : pytest.fixture + Monkeypatch the call to the remote metadata. + + """ + wfs = WebFeatureService(url='http://localhost/not_applicable', + version='1.1.0', + parse_remote_metadata=True) + assert 'gw_meetnetten:meetnetten' in wfs.contents + layer = wfs.contents['gw_meetnetten:meetnetten'] + + mdrecords = layer.get_metadata() + assert type(mdrecords) is list + assert len(mdrecords) == 1 + + for m in mdrecords: + assert type(m) is owslib.iso_3.MD_Metadata \ No newline at end of file