geonode-pycsw 3.0.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geonode_pycsw-3.0.0b2.dist-info/METADATA +73 -0
- geonode_pycsw-3.0.0b2.dist-info/RECORD +382 -0
- geonode_pycsw-3.0.0b2.dist-info/WHEEL +5 -0
- geonode_pycsw-3.0.0b2.dist-info/entry_points.txt +2 -0
- geonode_pycsw-3.0.0b2.dist-info/licenses/LICENSE.txt +26 -0
- geonode_pycsw-3.0.0b2.dist-info/top_level.txt +1 -0
- pycsw/__init__.py +33 -0
- pycsw/core/__init__.py +29 -0
- pycsw/core/admin.py +703 -0
- pycsw/core/config.py +621 -0
- pycsw/core/etree.py +43 -0
- pycsw/core/formats/__init__.py +29 -0
- pycsw/core/formats/fmt_json.py +69 -0
- pycsw/core/log.py +71 -0
- pycsw/core/metadata.py +1996 -0
- pycsw/core/pygeofilter_evaluate.py +83 -0
- pycsw/core/repository.py +941 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/_wrapper.xsd +14 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswAll.xsd +33 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswCommon.xsd +71 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswGetCapabilities.xsd +80 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswGetDomain.xsd +146 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswGetRecordById.xsd +58 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswGetRecords.xsd +391 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswHarvest.xsd +95 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswTransaction.xsd +187 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/cswUnHarvest.xsd +77 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/rec-dcmes.xsd +245 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/rec-dcterms.xsd +101 -0
- pycsw/core/schemas/ogc/cat/csw/3.0/record.xsd +170 -0
- pycsw/core/schemas/ogc/csw/2.0.2/CSW-discovery.xsd +494 -0
- pycsw/core/schemas/ogc/csw/2.0.2/CSW-publication.xsd +242 -0
- pycsw/core/schemas/ogc/csw/2.0.2/rec-dcmes.xsd +199 -0
- pycsw/core/schemas/ogc/csw/2.0.2/rec-dcterms.xsd +94 -0
- pycsw/core/schemas/ogc/csw/2.0.2/record.xsd +138 -0
- pycsw/core/schemas/ogc/filter/1.1.0/expr.xsd +67 -0
- pycsw/core/schemas/ogc/filter/1.1.0/filter.xsd +265 -0
- pycsw/core/schemas/ogc/filter/1.1.0/filterCapabilities.xsd +171 -0
- pycsw/core/schemas/ogc/filter/1.1.0/sort.xsd +46 -0
- pycsw/core/schemas/ogc/filter/2.0/_wrapper.xsd +5 -0
- pycsw/core/schemas/ogc/filter/2.0/expr.xsd +44 -0
- pycsw/core/schemas/ogc/filter/2.0/filter.xsd +396 -0
- pycsw/core/schemas/ogc/filter/2.0/filterAll.xsd +23 -0
- pycsw/core/schemas/ogc/filter/2.0/filterCapabilities.xsd +286 -0
- pycsw/core/schemas/ogc/filter/2.0/query.xsd +70 -0
- pycsw/core/schemas/ogc/filter/2.0/sort.xsd +49 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/basicTypes.xsd +278 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/coordinateOperations.xsd +789 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/coordinateReferenceSystems.xsd +429 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/coordinateSystems.xsd +408 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/coverage.xsd +451 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/dataQuality.xsd +129 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/datums.xsd +484 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/defaultStyle.xsd +454 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/dictionary.xsd +137 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/direction.xsd +72 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/dynamicFeature.xsd +115 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/feature.xsd +199 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/geometryAggregates.xsd +430 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/geometryBasic0d1d.xsd +602 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/geometryBasic2d.xsd +213 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/geometryComplexes.xsd +141 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/geometryPrimitives.xsd +1609 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/gml.xsd +22 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/gmlBase.xsd +294 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/grids.xsd +76 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/measures.xsd +200 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/observation.xsd +96 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/referenceSystems.xsd +211 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/temporal.xsd +332 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/temporalReferenceSystems.xsd +251 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/temporalTopology.xsd +186 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/topology.xsd +459 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/units.xsd +170 -0
- pycsw/core/schemas/ogc/gml/3.1.1/base/valueObjects.xsd +361 -0
- pycsw/core/schemas/ogc/gml/3.1.1/smil/smil20-language.xsd +117 -0
- pycsw/core/schemas/ogc/gml/3.1.1/smil/smil20.xsd +234 -0
- pycsw/core/schemas/ogc/gml/3.2.1/basicTypes.xsd +268 -0
- pycsw/core/schemas/ogc/gml/3.2.1/coordinateOperations.xsd +525 -0
- pycsw/core/schemas/ogc/gml/3.2.1/coordinateReferenceSystems.xsd +373 -0
- pycsw/core/schemas/ogc/gml/3.2.1/coordinateSystems.xsd +297 -0
- pycsw/core/schemas/ogc/gml/3.2.1/coverage.xsd +292 -0
- pycsw/core/schemas/ogc/gml/3.2.1/datums.xsd +287 -0
- pycsw/core/schemas/ogc/gml/3.2.1/defaultStyle.xsd +453 -0
- pycsw/core/schemas/ogc/gml/3.2.1/deprecatedTypes.xsd +1133 -0
- pycsw/core/schemas/ogc/gml/3.2.1/dictionary.xsd +90 -0
- pycsw/core/schemas/ogc/gml/3.2.1/direction.xsd +84 -0
- pycsw/core/schemas/ogc/gml/3.2.1/dynamicFeature.xsd +109 -0
- pycsw/core/schemas/ogc/gml/3.2.1/feature.xsd +94 -0
- pycsw/core/schemas/ogc/gml/3.2.1/geometryAggregates.xsd +197 -0
- pycsw/core/schemas/ogc/gml/3.2.1/geometryBasic0d1d.xsd +277 -0
- pycsw/core/schemas/ogc/gml/3.2.1/geometryBasic2d.xsd +124 -0
- pycsw/core/schemas/ogc/gml/3.2.1/geometryComplexes.xsd +95 -0
- pycsw/core/schemas/ogc/gml/3.2.1/geometryPrimitives.xsd +846 -0
- pycsw/core/schemas/ogc/gml/3.2.1/gml.xsd +20 -0
- pycsw/core/schemas/ogc/gml/3.2.1/gmlBase.xsd +185 -0
- pycsw/core/schemas/ogc/gml/3.2.1/grids.xsd +64 -0
- pycsw/core/schemas/ogc/gml/3.2.1/measures.xsd +68 -0
- pycsw/core/schemas/ogc/gml/3.2.1/observation.xsd +95 -0
- pycsw/core/schemas/ogc/gml/3.2.1/referenceSystems.xsd +70 -0
- pycsw/core/schemas/ogc/gml/3.2.1/temporal.xsd +269 -0
- pycsw/core/schemas/ogc/gml/3.2.1/temporalReferenceSystems.xsd +189 -0
- pycsw/core/schemas/ogc/gml/3.2.1/temporalTopology.xsd +119 -0
- pycsw/core/schemas/ogc/gml/3.2.1/topology.xsd +386 -0
- pycsw/core/schemas/ogc/gml/3.2.1/units.xsd +162 -0
- pycsw/core/schemas/ogc/gml/3.2.1/valueObjects.xsd +205 -0
- pycsw/core/schemas/ogc/ogcapi/records/part1/1.0/ogcapi-records-1.yaml +932 -0
- pycsw/core/schemas/ogc/ows/1.0.0/ows19115subset.xsd +222 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsAll.xsd +20 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsCommon.xsd +155 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsDataIdentification.xsd +112 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsExceptionReport.xsd +67 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsGetCapabilities.xsd +108 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsOperationsMetadata.xsd +161 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsServiceIdentification.xsd +55 -0
- pycsw/core/schemas/ogc/ows/1.0.0/owsServiceProvider.xsd +46 -0
- pycsw/core/schemas/ogc/ows/1.1.0/ows19115subset.xsd +236 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsAll.xsd +23 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsCommon.xsd +158 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsContents.xsd +87 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsDataIdentification.xsd +128 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsDomainType.xsd +280 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsExceptionReport.xsd +77 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsGetCapabilities.xsd +113 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsGetResourceByID.xsd +52 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsInputOutputData.xsd +60 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsManifest.xsd +125 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsOperationsMetadata.xsd +141 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsServiceIdentification.xsd +61 -0
- pycsw/core/schemas/ogc/ows/1.1.0/owsServiceProvider.xsd +48 -0
- pycsw/core/schemas/ogc/ows/2.0/ows19115subset.xsd +364 -0
- pycsw/core/schemas/ogc/ows/2.0/owsAdditionalParameters.xsd +114 -0
- pycsw/core/schemas/ogc/ows/2.0/owsAll.xsd +29 -0
- pycsw/core/schemas/ogc/ows/2.0/owsCommon.xsd +275 -0
- pycsw/core/schemas/ogc/ows/2.0/owsContents.xsd +163 -0
- pycsw/core/schemas/ogc/ows/2.0/owsDataIdentification.xsd +202 -0
- pycsw/core/schemas/ogc/ows/2.0/owsDomainType.xsd +388 -0
- pycsw/core/schemas/ogc/ows/2.0/owsExceptionReport.xsd +126 -0
- pycsw/core/schemas/ogc/ows/2.0/owsGetCapabilities.xsd +220 -0
- pycsw/core/schemas/ogc/ows/2.0/owsGetResourceByID.xsd +83 -0
- pycsw/core/schemas/ogc/ows/2.0/owsInputOutputData.xsd +98 -0
- pycsw/core/schemas/ogc/ows/2.0/owsManifest.xsd +181 -0
- pycsw/core/schemas/ogc/ows/2.0/owsOperationsMetadata.xsd +234 -0
- pycsw/core/schemas/ogc/ows/2.0/owsServiceIdentification.xsd +98 -0
- pycsw/core/schemas/ogc/ows/2.0/owsServiceProvider.xsd +64 -0
- pycsw/core/schemas/w3c/1999/xlink.xsd +271 -0
- pycsw/core/schemas/w3c/2001/xml.xsd +287 -0
- pycsw/core/util.py +552 -0
- pycsw/oaipmh.py +311 -0
- pycsw/ogc/__init__.py +29 -0
- pycsw/ogc/api/__init__.py +28 -0
- pycsw/ogc/api/oapi.py +558 -0
- pycsw/ogc/api/records.py +1414 -0
- pycsw/ogc/api/templates/_base.html +76 -0
- pycsw/ogc/api/templates/collection.html +44 -0
- pycsw/ogc/api/templates/collections.html +45 -0
- pycsw/ogc/api/templates/conformance.html +21 -0
- pycsw/ogc/api/templates/exception.html +8 -0
- pycsw/ogc/api/templates/item.html +228 -0
- pycsw/ogc/api/templates/items.html +337 -0
- pycsw/ogc/api/templates/landing_page.html +27 -0
- pycsw/ogc/api/templates/openapi.html +58 -0
- pycsw/ogc/api/templates/queryables.html +50 -0
- pycsw/ogc/api/templates/stac_items.html +173 -0
- pycsw/ogc/api/templates/static/favicon.ico +0 -0
- pycsw/ogc/api/templates/static/logo-horizontal.png +0 -0
- pycsw/ogc/api/templates/static/logo-vertical-darkbg.png +0 -0
- pycsw/ogc/api/util.py +252 -0
- pycsw/ogc/csw/__init__.py +29 -0
- pycsw/ogc/csw/cql.py +133 -0
- pycsw/ogc/csw/csw2.py +2042 -0
- pycsw/ogc/csw/csw3.py +2193 -0
- pycsw/ogc/fes/__init__.py +29 -0
- pycsw/ogc/fes/fes1.py +433 -0
- pycsw/ogc/fes/fes2.py +451 -0
- pycsw/ogc/gml/__init__.py +29 -0
- pycsw/ogc/gml/gml3.py +240 -0
- pycsw/ogc/gml/gml32.py +243 -0
- pycsw/opensearch.py +857 -0
- pycsw/plugins/__init__.py +29 -0
- pycsw/plugins/outputschemas/__init__.py +31 -0
- pycsw/plugins/outputschemas/atom.py +143 -0
- pycsw/plugins/outputschemas/datacite.py +375 -0
- pycsw/plugins/outputschemas/dif.py +213 -0
- pycsw/plugins/outputschemas/fgdc.py +180 -0
- pycsw/plugins/outputschemas/gm03.py +240 -0
- pycsw/plugins/profiles/__init__.py +29 -0
- pycsw/plugins/profiles/apiso/__init__.py +29 -0
- pycsw/plugins/profiles/apiso/apiso.py +757 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd +13 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gco/basicTypes.xsd +429 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gco/gco.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gco/gcoBase.xsd +61 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/applicationSchema.xsd +42 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/citation.xsd +275 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/constraints.xsd +106 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/content.xsd +188 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/dataQuality.xsd +554 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/distribution.xsd +202 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/extent.xsd +205 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/freeText.xsd +122 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/gmd.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/identification.xsd +348 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/maintenance.xsd +86 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/metadataApplication.xsd +175 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/metadataEntity.xsd +70 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/metadataExtension.xsd +99 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/portrayalCatalogue.xsd +36 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/referenceSystem.xsd +100 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmd/spatialRepresentation.xsd +237 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/basicTypes.xsd +267 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coordinateOperations.xsd +639 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coordinateReferenceSystems.xsd +526 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coordinateSystems.xsd +401 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/coverage.xsd +462 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/datums.xsd +342 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/dictionary.xsd +129 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/direction.xsd +80 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/dynamicFeature.xsd +142 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/feature.xsd +215 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryAggregates.xsd +216 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryBasic0d1d.xsd +304 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryBasic2d.xsd +123 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryComplexes.xsd +89 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/geometryPrimitives.xsd +892 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/gml.xsd +14 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/gmlBase.xsd +305 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/grids.xsd +58 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/measures.xsd +167 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/observation.xsd +90 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/referenceSystems.xsd +69 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/temporal.xsd +263 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/temporalReferenceSystems.xsd +183 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/temporalTopology.xsd +124 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/topology.xsd +372 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/units.xsd +156 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gml/valueObjects.xsd +212 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/catalogues.xsd +112 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/codelistItem.xsd +168 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/crsItem.xsd +1030 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/extendedTypes.xsd +75 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/gmx.xsd +2 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/gmxUsage.xsd +127 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gmx/uomItem.xsd +162 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gsr/gsr.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gsr/spatialReferencing.xsd +24 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gss/geometry.xsd +35 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gss/gss.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gts/gts.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/gts/temporalObjects.xsd +34 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/srv/serviceMetadata.xsd +197 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/srv/serviceModel.xsd +220 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20060504/srv/srv.xsd +13 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gco/basicTypes.xsd +431 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gco/gco.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gco/gcoBase.xsd +63 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/applicationSchema.xsd +43 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/citation.xsd +276 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/constraints.xsd +107 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/content.xsd +190 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/dataQuality.xsd +556 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/distribution.xsd +203 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/extent.xsd +206 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/freeText.xsd +123 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/gmd.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/identification.xsd +349 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/maintenance.xsd +87 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/metadataApplication.xsd +176 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/metadataEntity.xsd +71 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/metadataExtension.xsd +100 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/portrayalCatalogue.xsd +37 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/referenceSystem.xsd +101 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmd/spatialRepresentation.xsd +238 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/catalogues.xsd +113 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/codelistItem.xsd +169 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/crsItem.xsd +1031 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/extendedTypes.xsd +76 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/gmx.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/gmxUsage.xsd +128 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gmx/uomItem.xsd +163 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gsr/gsr.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gsr/spatialReferencing.xsd +25 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gss/geometry.xsd +36 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gss/gss.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gts/gts.xsd +12 -0
- pycsw/plugins/profiles/apiso/schemas/ogc/iso/19139/20070417/gts/temporalObjects.xsd +35 -0
- pycsw/plugins/profiles/ebrim/__init__.py +29 -0
- pycsw/plugins/profiles/ebrim/ebrim.py +174 -0
- pycsw/plugins/profiles/ebrim/schemas/ogc/csw/2.0.2/profiles/ebrim/1.0/csw-ebrim-iri.xsd +146 -0
- pycsw/plugins/profiles/ebrim/schemas/ogc/csw/2.0.2/profiles/ebrim/1.0/csw-ebrim.xsd +104 -0
- pycsw/plugins/profiles/iso19115p3/__init__.py +29 -0
- pycsw/plugins/profiles/iso19115p3/iso19115p3.py +854 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/cat.xsd +13 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/catalogues.xsd +53 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/codelistItem.xsd +54 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/crsItem.xsd +181 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cat/1.0/uomItem.xsd +38 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/1.0/cit.xsd +7 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/1.0/citation.xsd +514 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/2.0/cit.xsd +10 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/cit/2.0/citation.xsd +523 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gco/1.0/baseTypes2014.xsd +530 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gco/1.0/gco.xsd +16 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gcx/1.0/extendedTypes.xsd +92 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gcx/1.0/extendedTypes_autoFromShapeChange.xsd +60 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gcx/1.0/gcx.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gex/1.0/extent.xsd +241 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gex/1.0/gex.xsd +9 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gmw/1.0/gmlWrapperTypes2014.xsd +159 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/gmw/1.0/gmw.xsd +14 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/lan/1.0/lan.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/lan/1.0/language.xsd +140 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/1.0/acquisitionInformationImagery.xsd +622 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/1.0/mac.xsd +11 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/2.0/acquisitionInformationImagery.xsd +590 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/2.0/event.xsd +108 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mac/2.0/mac.xsd +10 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mas/1.0/applicationSchema.xsd +61 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mas/1.0/mas.xsd +9 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mcc/1.0/AbstractCommonClasses.xsd +358 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mcc/1.0/commonClasses.xsd +220 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mcc/1.0/mcc.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mco/1.0/constraints.xsd +188 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mco/1.0/mco.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md1/1.0/md1.xsd +9 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md1/1.0/metadataWExtendedType.xsd +4 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md2/1.0/md2.xsd +15 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/md2/1.0/metadataWithExtensions.xsd +4 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mda/1.0/mda.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mda/1.0/metadataApplication.xsd +200 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/1.0/mdb.xsd +14 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/1.0/metadataBase.xsd +98 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/2.0/mdb.xsd +20 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdb/2.0/metadataBase.xsd +102 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mds/1.0/mds.xsd +22 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mds/1.0/metadataDataServices.xsd +4 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdt/1.0/mdt.xsd +13 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mdt/1.0/metadataTransfer.xsd +111 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mex/1.0/metadataExtension.xsd +156 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mex/1.0/mex.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mmi/1.0/maintenance.xsd +76 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mmi/1.0/mmi.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mpc/1.0/mpc.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mpc/1.0/portrayalCatalogue.xsd +31 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/1.0/content.xsd +416 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/1.0/contentInformationImagery.xsd +185 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/1.0/mrc.xsd +11 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/2.0/content.xsd +419 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/2.0/contentInformationImagery.xsd +171 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrc/2.0/mrc.xsd +11 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrd/1.0/distribution.xsd +267 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrd/1.0/mrd.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mri/1.0/identification.xsd +517 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mri/1.0/mri.xsd +9 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/1.0/lineage.xsd +147 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/1.0/lineageImagery.xsd +236 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/1.0/mrl.xsd +9 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/2.0/lineage.xsd +147 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/2.0/lineageImagery.xsd +312 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrl/2.0/mrl.xsd +11 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrs/1.0/mrs.xsd +8 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/mrs/1.0/referenceSystem.xsd +47 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/1.0/msr.xsd +10 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/1.0/spatialRepresentation.xsd +375 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/1.0/spatialRepresentationImagery.xsd +119 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/2.0/msr.xsd +15 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/2.0/spatialRepresentation.xsd +381 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/msr/2.0/spatialRepresentationImagery.xsd +120 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.0/serviceInformation.xsd +272 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.0/srv.xsd +6 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.1/serviceInformation.xsd +278 -0
- pycsw/plugins/profiles/iso19115p3/schemas/ogc/iso/iso19115-3/srv/2.1/srv.xsd +6 -0
- pycsw/plugins/profiles/profile.py +141 -0
- pycsw/plugins/repository/__init__.py +29 -0
- pycsw/plugins/repository/odc/__init__.py +29 -0
- pycsw/plugins/repository/odc/odc.py +153 -0
- pycsw/server.py +938 -0
- pycsw/sru.py +217 -0
- pycsw/stac/__init__.py +29 -0
- pycsw/stac/api.py +571 -0
- pycsw/wsgi.py +233 -0
- pycsw/wsgi_flask.py +345 -0
pycsw/core/util.py
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# =================================================================
|
|
3
|
+
#
|
|
4
|
+
# Authors: Tom Kralidis <tomkralidis@gmail.com>
|
|
5
|
+
# Angelos Tzotsos <tzotsos@gmail.com>
|
|
6
|
+
# Ricardo Garcia Silva <ricardo.garcia.silva@gmail.com>
|
|
7
|
+
#
|
|
8
|
+
# Copyright (c) 2023 Tom Kralidis
|
|
9
|
+
# Copyright (c) 2015 Angelos Tzotsos
|
|
10
|
+
# Copyright (c) 2017 Ricardo Garcia Silva
|
|
11
|
+
#
|
|
12
|
+
# Permission is hereby granted, free of charge, to any person
|
|
13
|
+
# obtaining a copy of this software and associated documentation
|
|
14
|
+
# files (the "Software"), to deal in the Software without
|
|
15
|
+
# restriction, including without limitation the rights to use,
|
|
16
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
# copies of the Software, and to permit persons to whom the
|
|
18
|
+
# Software is furnished to do so, subject to the following
|
|
19
|
+
# conditions:
|
|
20
|
+
#
|
|
21
|
+
# The above copyright notice and this permission notice shall be
|
|
22
|
+
# included in all copies or substantial portions of the Software.
|
|
23
|
+
#
|
|
24
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
25
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
26
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
27
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
28
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
29
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
30
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
31
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
|
32
|
+
#
|
|
33
|
+
# =================================================================
|
|
34
|
+
|
|
35
|
+
from configparser import BasicInterpolation, ConfigParser
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
import importlib
|
|
38
|
+
import importlib.util
|
|
39
|
+
import json
|
|
40
|
+
import os
|
|
41
|
+
import re
|
|
42
|
+
import datetime
|
|
43
|
+
import logging
|
|
44
|
+
import sys
|
|
45
|
+
import time
|
|
46
|
+
import typing
|
|
47
|
+
|
|
48
|
+
from urllib.request import Request, urlopen
|
|
49
|
+
from urllib.parse import urlparse
|
|
50
|
+
from shapely.wkt import loads
|
|
51
|
+
from owslib.util import http_post
|
|
52
|
+
|
|
53
|
+
from pycsw.core.etree import etree, PARSER
|
|
54
|
+
|
|
55
|
+
LOGGER = logging.getLogger(__name__)
|
|
56
|
+
|
|
57
|
+
# Global variables for spatial ranking algorithm
|
|
58
|
+
ranking_enabled = False
|
|
59
|
+
ranking_pass = False
|
|
60
|
+
ranking_query_geometry = ''
|
|
61
|
+
|
|
62
|
+
# Lookups for the secure_filename function
|
|
63
|
+
# https://github.com/pallets/werkzeug/blob/778f482d1ac0c9e8e98f774d2595e9074e6984d7/werkzeug/utils.py#L30-L31
|
|
64
|
+
_filename_ascii_strip_re = re.compile(r'[^A-Za-z0-9_.-]')
|
|
65
|
+
_windows_device_files = ('CON', 'AUX', 'COM1', 'COM2', 'COM3', 'COM4', 'LPT1',
|
|
66
|
+
'LPT2', 'LPT3', 'PRN', 'NUL')
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_today_and_now():
|
|
70
|
+
"""Get the date, right now, in ISO8601"""
|
|
71
|
+
return time.strftime('%Y-%m-%dT%H:%M:%SZ', time.localtime())
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def datetime2iso8601(value):
|
|
75
|
+
"""Return a datetime value as ISO8601
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
value: datetime.date or datetime.datetime
|
|
80
|
+
The temporal value to be converted
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
str
|
|
85
|
+
A string with the temporal value in ISO8601 format.
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
if isinstance(value, datetime.datetime):
|
|
90
|
+
if value == value.replace(hour=0, minute=0, second=0, microsecond=0):
|
|
91
|
+
result = value.strftime("%Y-%m-%d")
|
|
92
|
+
else:
|
|
93
|
+
result = value.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
94
|
+
else: # value is a datetime.date
|
|
95
|
+
result = value.strftime('%Y-%m-%d')
|
|
96
|
+
return result
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def get_time_iso2unix(isotime):
|
|
100
|
+
"""Convert ISO8601 to UNIX timestamp"""
|
|
101
|
+
return int(time.mktime(time.strptime(
|
|
102
|
+
isotime, '%Y-%m-%dT%H:%M:%SZ'))) - time.timezone
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def get_version_integer(version):
|
|
106
|
+
"""Get an integer of the OGC version value x.y.z
|
|
107
|
+
|
|
108
|
+
In case of an invalid version string this returns -1.
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
version: str
|
|
113
|
+
The version string that is to be transformed into an integer
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
int
|
|
118
|
+
The transformed version
|
|
119
|
+
|
|
120
|
+
Raises
|
|
121
|
+
------
|
|
122
|
+
RuntimeError
|
|
123
|
+
When the input version is neither a string or None
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
xyz = version.split('.')
|
|
129
|
+
if len(xyz) == 3:
|
|
130
|
+
result = int(xyz[0]) * 10000 + int(xyz[1]) * 100 + int(xyz[2])
|
|
131
|
+
else:
|
|
132
|
+
result = -1
|
|
133
|
+
except AttributeError as err:
|
|
134
|
+
raise RuntimeError('%s' % str(err)) from err
|
|
135
|
+
return result
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def nspath_eval(xpath, nsmap):
|
|
139
|
+
"""Return an etree friendly xpath.
|
|
140
|
+
|
|
141
|
+
This function converts XPath expressions that use prefixes into
|
|
142
|
+
their full namespace. This is the form expected by lxml [1]_.
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
xpath: str
|
|
147
|
+
The XPath expression to be converted
|
|
148
|
+
nsmap: dict
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
str
|
|
153
|
+
The XPath expression using namespaces instead of prefixes.
|
|
154
|
+
|
|
155
|
+
References
|
|
156
|
+
----------
|
|
157
|
+
.. [1] http://lxml.de/tutorial.html#namespaces
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
out = []
|
|
162
|
+
for node in xpath.split('/'):
|
|
163
|
+
chunks = node.split(":")
|
|
164
|
+
if len(chunks) == 2:
|
|
165
|
+
prefix, element = node.split(':')
|
|
166
|
+
out.append('{%s}%s' % (nsmap[prefix], element))
|
|
167
|
+
elif len(chunks) == 1:
|
|
168
|
+
out.append(node)
|
|
169
|
+
else:
|
|
170
|
+
raise RuntimeError(f"Invalid XPath expression: {xpath}")
|
|
171
|
+
return '/'.join(out)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def wktenvelope2bbox(envelope):
|
|
175
|
+
"""returns bbox string of WKT ENVELOPE definition"""
|
|
176
|
+
|
|
177
|
+
tmparr = [x.strip() for x in envelope.split('(')[1].split(')')[0].split(',')]
|
|
178
|
+
bbox = '%s,%s,%s,%s' % (tmparr[0], tmparr[3], tmparr[1], tmparr[2])
|
|
179
|
+
return bbox
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def geojson_geometry2bbox(geometry):
|
|
183
|
+
"""returns bbox string of GeoJSON geometry"""
|
|
184
|
+
|
|
185
|
+
geom_type = geometry.get('type')
|
|
186
|
+
coords = geometry.get('coordinates')
|
|
187
|
+
|
|
188
|
+
if geom_type == 'Point':
|
|
189
|
+
bbox = '%s,%s,%s,%s' % (coords[0], coords[1], coords[0], coords[1])
|
|
190
|
+
elif geom_type == 'Polygon':
|
|
191
|
+
bbox = '%s,%s,%s,%s' % (coords[0][0][0], coords[0][0][1], coords[0][2][0], coords[0][2][1])
|
|
192
|
+
|
|
193
|
+
return bbox
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def wkt2geom(ewkt, bounds=True):
|
|
197
|
+
"""Return Shapely geometry object based on WKT/EWKT
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
ewkt: str
|
|
202
|
+
The geometry to convert, in Extended Well-Known Text format. More info
|
|
203
|
+
on this format at [1]_
|
|
204
|
+
bounds: bool
|
|
205
|
+
Whether to return only the bounding box of the geometry as a tuple or
|
|
206
|
+
the full shapely geometry instance
|
|
207
|
+
|
|
208
|
+
Returns
|
|
209
|
+
-------
|
|
210
|
+
shapely.geometry.base.BaseGeometry or tuple
|
|
211
|
+
|
|
212
|
+
Depending on the value of the ``bounds`` parameter, returns either
|
|
213
|
+
the shapely geometry instance or a tuple with the bounding box.
|
|
214
|
+
|
|
215
|
+
References
|
|
216
|
+
----------
|
|
217
|
+
.. [1] http://postgis.net/docs/ST_GeomFromEWKT.html
|
|
218
|
+
|
|
219
|
+
"""
|
|
220
|
+
|
|
221
|
+
wkt = ewkt.split(";")[-1] if ewkt.find("SRID") != -1 else ewkt
|
|
222
|
+
if wkt.startswith('ENVELOPE'):
|
|
223
|
+
wkt = bbox2wktpolygon(wktenvelope2bbox(wkt))
|
|
224
|
+
geometry = loads(wkt)
|
|
225
|
+
return geometry.envelope.bounds if bounds else geometry
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def bbox2wktpolygon(bbox):
|
|
229
|
+
"""Return OGC WKT Polygon of a simple bbox string
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
bbox: str
|
|
234
|
+
The bounding box to convert to WKT.
|
|
235
|
+
|
|
236
|
+
Returns
|
|
237
|
+
-------
|
|
238
|
+
str
|
|
239
|
+
The bounding box's Well-Known Text representation.
|
|
240
|
+
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
precision = int(os.environ.get('COORDINATE_PRECISION', 2))
|
|
244
|
+
if bbox.startswith('ENVELOPE'):
|
|
245
|
+
bbox = wktenvelope2bbox(bbox)
|
|
246
|
+
minx, miny, maxx, maxy = [f"{float(coord):.{precision}f}" for coord in bbox.split(",")]
|
|
247
|
+
wktGeometry = 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' \
|
|
248
|
+
% (minx, miny, minx, maxy, maxx, maxy, maxx, miny, minx, miny)
|
|
249
|
+
return wktGeometry
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def transform_mappings(queryables, typename):
|
|
253
|
+
"""Transform metadata model mappings
|
|
254
|
+
|
|
255
|
+
Parameters
|
|
256
|
+
----------
|
|
257
|
+
queryables: dict
|
|
258
|
+
typename: dict
|
|
259
|
+
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
for item in queryables:
|
|
263
|
+
try:
|
|
264
|
+
matching_typename = [key for key, value in typename.items() if
|
|
265
|
+
value == item][0]
|
|
266
|
+
queryable_value = queryables[matching_typename]
|
|
267
|
+
queryables[item] = {
|
|
268
|
+
"xpath": queryable_value["xpath"],
|
|
269
|
+
"dbcol": queryable_value["dbcol"],
|
|
270
|
+
}
|
|
271
|
+
except IndexError:
|
|
272
|
+
pass
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def getqattr(obj, name):
|
|
276
|
+
"""Get value of an object, safely"""
|
|
277
|
+
result = None
|
|
278
|
+
try:
|
|
279
|
+
item = getattr(obj, name)
|
|
280
|
+
value = item()
|
|
281
|
+
if "link" in name: # create link format
|
|
282
|
+
links = []
|
|
283
|
+
for link in value:
|
|
284
|
+
links.append(','.join(list(link)))
|
|
285
|
+
result = '^'.join(links)
|
|
286
|
+
else:
|
|
287
|
+
result = value
|
|
288
|
+
except TypeError: # item is not callable
|
|
289
|
+
try:
|
|
290
|
+
result = datetime2iso8601(item)
|
|
291
|
+
except AttributeError: # item is not date(time)
|
|
292
|
+
result = item
|
|
293
|
+
except AttributeError: # obj does not have a name property
|
|
294
|
+
pass
|
|
295
|
+
return result
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def http_request(method, url, request=None, timeout=30):
|
|
299
|
+
"""Perform HTTP request"""
|
|
300
|
+
if method == 'POST':
|
|
301
|
+
return http_post(url, request, timeout=timeout)
|
|
302
|
+
else: # GET
|
|
303
|
+
request = Request(url)
|
|
304
|
+
request.add_header('User-Agent', 'pycsw (https://pycsw.org/)')
|
|
305
|
+
return urlopen(request, timeout=timeout).read()
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def bind_url(url):
|
|
309
|
+
"""binds an HTTP GET query string endpoint"""
|
|
310
|
+
parsed_url = urlparse(url)
|
|
311
|
+
if parsed_url.query == "":
|
|
312
|
+
binder = "?"
|
|
313
|
+
elif parsed_url.query.endswith("&"):
|
|
314
|
+
binder = ""
|
|
315
|
+
else:
|
|
316
|
+
binder = "&"
|
|
317
|
+
return "".join((parsed_url.geturl(), binder))
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def ip_in_network_cidr(ip, net):
|
|
321
|
+
"""decipher whether IP is within CIDR range"""
|
|
322
|
+
ipaddr = int(
|
|
323
|
+
''.join(['%02x' % int(x) for x in ip.split('.')]),
|
|
324
|
+
16
|
|
325
|
+
)
|
|
326
|
+
netstr, bits = net.split('/')
|
|
327
|
+
netaddr = int(
|
|
328
|
+
''.join(['%02x' % int(x) for x in netstr.split('.')]),
|
|
329
|
+
16
|
|
330
|
+
)
|
|
331
|
+
mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
|
|
332
|
+
return (ipaddr & mask) == (netaddr & mask)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def ipaddress_in_whitelist(ipaddress, whitelist):
|
|
336
|
+
"""decipher whether IP is in IP whitelist
|
|
337
|
+
|
|
338
|
+
IP whitelist is a list supporting:
|
|
339
|
+
- single IP address (e.g. 192.168.0.1)
|
|
340
|
+
- IP range using CIDR (e.g. 192.168.0/22)
|
|
341
|
+
- IP range using subnet wildcard (e.g. 192.168.0.*, 192.168.*)
|
|
342
|
+
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
if ipaddress in whitelist:
|
|
346
|
+
return True
|
|
347
|
+
else:
|
|
348
|
+
for white in whitelist:
|
|
349
|
+
if white.find('/') != -1: # CIDR
|
|
350
|
+
if ip_in_network_cidr(ipaddress, white):
|
|
351
|
+
return True
|
|
352
|
+
elif white.find('*') != -1: # subnet wildcard
|
|
353
|
+
if ipaddress.startswith(white.split('*')[0]):
|
|
354
|
+
return True
|
|
355
|
+
return False
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def get_anytext(bag):
|
|
359
|
+
"""
|
|
360
|
+
generate bag of text for free text searches
|
|
361
|
+
accepts list of words, string of XML, or etree.Element
|
|
362
|
+
"""
|
|
363
|
+
|
|
364
|
+
if isinstance(bag, list): # list of words
|
|
365
|
+
return ' '.join([_f for _f in bag if _f]).strip()
|
|
366
|
+
else: # xml
|
|
367
|
+
if isinstance(bag, bytes) or isinstance(bag, str):
|
|
368
|
+
# serialize to lxml
|
|
369
|
+
bag = etree.fromstring(bag, PARSER)
|
|
370
|
+
# get all XML element content
|
|
371
|
+
return ' '.join([value.strip() for value in bag.xpath('//text()')])
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
# https://stackoverflow.com/a/39234154
|
|
375
|
+
def get_anytext_from_obj(obj):
|
|
376
|
+
"""
|
|
377
|
+
generate bag of text for free text searches
|
|
378
|
+
accepts dict, list or string
|
|
379
|
+
"""
|
|
380
|
+
|
|
381
|
+
if isinstance(obj, dict):
|
|
382
|
+
for key, value in obj.items():
|
|
383
|
+
if isinstance(value, (list, dict)):
|
|
384
|
+
yield from get_anytext_from_obj(value)
|
|
385
|
+
else:
|
|
386
|
+
yield value
|
|
387
|
+
elif isinstance(obj, list):
|
|
388
|
+
for value in obj:
|
|
389
|
+
if isinstance(value, (list, dict)):
|
|
390
|
+
yield from get_anytext_from_obj(value)
|
|
391
|
+
else:
|
|
392
|
+
yield value
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
# https://github.com/pallets/werkzeug/blob/778f482d1ac0c9e8e98f774d2595e9074e6984d7/werkzeug/utils.py#L253
|
|
396
|
+
def secure_filename(filename):
|
|
397
|
+
r"""Pass it a filename and it will return a secure version of it. This
|
|
398
|
+
filename can then safely be stored on a regular file system and passed
|
|
399
|
+
to :func:`os.path.join`. The filename returned is an ASCII only string
|
|
400
|
+
for maximum portability.
|
|
401
|
+
|
|
402
|
+
On windows systems the function also makes sure that the file is not
|
|
403
|
+
named after one of the special device files.
|
|
404
|
+
|
|
405
|
+
>>> secure_filename("My cool movie.mov")
|
|
406
|
+
'My_cool_movie.mov'
|
|
407
|
+
>>> secure_filename("../../../etc/passwd")
|
|
408
|
+
'etc_passwd'
|
|
409
|
+
>>> secure_filename(u'i contain cool \xfcml\xe4uts.txt')
|
|
410
|
+
'i_contain_cool_umlauts.txt'
|
|
411
|
+
|
|
412
|
+
The function might return an empty filename. It's your responsibility
|
|
413
|
+
to ensure that the filename is unique and that you abort or
|
|
414
|
+
generate a random filename if the function returned an empty one.
|
|
415
|
+
|
|
416
|
+
.. versionadded:: 0.5
|
|
417
|
+
|
|
418
|
+
:param filename: the filename to secure
|
|
419
|
+
"""
|
|
420
|
+
if isinstance(filename, str):
|
|
421
|
+
from unicodedata import normalize
|
|
422
|
+
filename = normalize('NFKD', filename).encode('ascii', 'ignore')
|
|
423
|
+
filename = filename.decode('ascii')
|
|
424
|
+
for sep in os.path.sep, os.path.altsep:
|
|
425
|
+
if sep:
|
|
426
|
+
filename = filename.replace(sep, ' ')
|
|
427
|
+
filename = str(_filename_ascii_strip_re.sub('', '_'.join(
|
|
428
|
+
filename.split()))).strip('._')
|
|
429
|
+
|
|
430
|
+
# on nt a couple of special files are present in each folder. We
|
|
431
|
+
# have to ensure that the target file is not such a filename. In
|
|
432
|
+
# this case we prepend an underline
|
|
433
|
+
if os.name == 'nt' and filename and \
|
|
434
|
+
filename.split('.')[0].upper() in _windows_device_files:
|
|
435
|
+
filename = '_' + filename
|
|
436
|
+
|
|
437
|
+
return filename
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def jsonify_links(links):
|
|
441
|
+
"""
|
|
442
|
+
pycsw:Links column data handler.
|
|
443
|
+
casts old or new style links into JSON objects
|
|
444
|
+
"""
|
|
445
|
+
try:
|
|
446
|
+
LOGGER.debug('JSON link')
|
|
447
|
+
linkset = json.loads(links)
|
|
448
|
+
return linkset
|
|
449
|
+
except json.decoder.JSONDecodeError: # try CSV parsing
|
|
450
|
+
LOGGER.debug('old style CSV link')
|
|
451
|
+
json_links = []
|
|
452
|
+
for link in links.split('^'):
|
|
453
|
+
tokens = link.split(',')
|
|
454
|
+
json_links.append({
|
|
455
|
+
'name': tokens[0] or None,
|
|
456
|
+
'description': tokens[1] or None,
|
|
457
|
+
'protocol': tokens[2] or None,
|
|
458
|
+
'url': tokens[3] or None
|
|
459
|
+
})
|
|
460
|
+
return json_links
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class EnvInterpolation(BasicInterpolation):
|
|
464
|
+
"""
|
|
465
|
+
Interpolation which expands environment variables in values.
|
|
466
|
+
from: https://stackoverflow.com/a/49529659
|
|
467
|
+
"""
|
|
468
|
+
|
|
469
|
+
def before_get(self, parser, section, option, value, defaults):
|
|
470
|
+
value = super().before_get(parser, section, option, value, defaults)
|
|
471
|
+
return os.path.expandvars(value)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def parse_ini_config(config_path) -> ConfigParser:
|
|
475
|
+
"""
|
|
476
|
+
Helper function to parse a .ini configuration file
|
|
477
|
+
|
|
478
|
+
:param config_path: filepath
|
|
479
|
+
|
|
480
|
+
:returns: ConfigParser object
|
|
481
|
+
"""
|
|
482
|
+
|
|
483
|
+
config = ConfigParser(interpolation=EnvInterpolation())
|
|
484
|
+
with open(config_path, encoding='utf-8') as scp:
|
|
485
|
+
config.read_file(scp)
|
|
486
|
+
return config
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def is_none_or_empty(value):
|
|
490
|
+
"""
|
|
491
|
+
Helper function to detect if value is None or empty
|
|
492
|
+
|
|
493
|
+
:param value: value to evaluate
|
|
494
|
+
|
|
495
|
+
:returns: bool of whether the value is None or empty
|
|
496
|
+
"""
|
|
497
|
+
|
|
498
|
+
if value is None or len(value.strip()) == 0:
|
|
499
|
+
return True
|
|
500
|
+
|
|
501
|
+
return False
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def programmatic_import(target_module: str) -> typing.Optional[typing.Any]:
|
|
505
|
+
result = None
|
|
506
|
+
target_module_path = Path(target_module)
|
|
507
|
+
if target_module_path.is_file():
|
|
508
|
+
module_name = target_module_path.stem
|
|
509
|
+
# this is an adaptation of the Python docs on using importlib to import a
|
|
510
|
+
# filepath:
|
|
511
|
+
# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
|
|
512
|
+
spec = importlib.util.spec_from_file_location(
|
|
513
|
+
module_name, target_module_path)
|
|
514
|
+
if spec is not None:
|
|
515
|
+
module = importlib.util.module_from_spec(spec)
|
|
516
|
+
sys.modules[module_name] = module
|
|
517
|
+
spec.loader.exec_module(module)
|
|
518
|
+
result = module
|
|
519
|
+
else:
|
|
520
|
+
try:
|
|
521
|
+
result = importlib.import_module(target_module)
|
|
522
|
+
except ModuleNotFoundError:
|
|
523
|
+
pass
|
|
524
|
+
return result
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def load_custom_repo_mappings(repository_mappings: str) -> typing.Optional[typing.Dict]:
|
|
528
|
+
imported_mappings_module = programmatic_import(repository_mappings)
|
|
529
|
+
result = None
|
|
530
|
+
if imported_mappings_module is not None:
|
|
531
|
+
result = getattr(imported_mappings_module, "MD_CORE_MODEL", None)
|
|
532
|
+
return result
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
def str2bool(value: typing.Union[bool, str]) -> bool:
|
|
536
|
+
"""
|
|
537
|
+
helper function to return Python boolean
|
|
538
|
+
type (source: https://stackoverflow.com/a/715468)
|
|
539
|
+
|
|
540
|
+
:param value: value to be evaluated
|
|
541
|
+
|
|
542
|
+
:returns: `bool` of whether the value is boolean-ish
|
|
543
|
+
"""
|
|
544
|
+
|
|
545
|
+
value2 = False
|
|
546
|
+
|
|
547
|
+
if isinstance(value, bool):
|
|
548
|
+
value2 = value
|
|
549
|
+
else:
|
|
550
|
+
value2 = value.lower() in ('yes', 'true', 't', '1', 'on')
|
|
551
|
+
|
|
552
|
+
return value2
|