123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #!/usr/bin/env python3
- ############################################################################
- #
- # MODULE: v.in.wfs
- # AUTHOR(S): Markus Neteler. neteler itc it
- # Hamish Bowman
- # Converted to Python by Glynn Clements
- # PURPOSE: WFS support
- # COPYRIGHT: (C) 2006-2012 Markus Neteler and the GRASS Development Team
- #
- # This program is free software under the GNU General
- # Public License (>=v2). Read the file COPYING that
- # comes with GRASS for details.
- #
- # GetFeature example:
- # http://mapserver.gdf-hannover.de/cgi-bin/grassuserwfs?REQUEST=GetFeature&SERVICE=WFS&VERSION=1.0.0
- #############################################################################
- #
- # TODO: suggest to depend on the OWSLib for OGC web service needs
- # http://pypi.python.org/pypi/OWSLib
- #
- # %Module
- # % description: Imports GetFeature from a WFS server.
- # % keyword: vector
- # % keyword: import
- # % keyword: OGC web services
- # % keyword: OGC WFS
- # %end
- # %option
- # % key: url
- # % type: string
- # % description: Base URL starting with 'http' and ending in '?'
- # % required: yes
- # %end
- # %option G_OPT_V_OUTPUT
- # %end
- # %option
- # % key: name
- # % type: string
- # % description: Comma separated names of data layers to download
- # % multiple: yes
- # % required: no
- # %end
- # %option
- # % key: srs
- # % type: string
- # % label: Specify alternate spatial reference system (example: EPSG:4326)
- # % description: The given code must be supported by the server, consult the capabilities file
- # % required: no
- # %end
- # %option
- # % key: maximum_features
- # % type: integer
- # % label: Maximum number of features to download
- # % description: (default: unlimited)
- # %end
- # %option
- # % key: start_index
- # % type: integer
- # % label: Skip earlier feature IDs and start downloading at this one
- # % description: (default: start with the first feature)
- # %end
- # %option
- # % key: username
- # % type: string
- # % required: no
- # % multiple: no
- # % label: Username or file with username or environment variable name with username
- # %end
- # %option
- # % key: password
- # % type: string
- # % required: no
- # % multiple: no
- # % label: Password or file with password or environment variable name with password
- # %end
- # %flag
- # % key: l
- # todo #% description: List available layers and exit
- # % description: Download server capabilities to 'wms_capabilities.xml' in the current directory and exit
- # % suppress_required: yes
- # %end
- # %flag
- # % key: r
- # % description: Restrict fetch to features which touch the current region
- # %end
- import os
- import sys
- from grass.script.utils import try_remove
- from grass.script import core as grass
- try:
- from urllib2 import urlopen, URLError, HTTPError
- from urllib2 import build_opener, install_opener
- from urllib2 import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler
- except ImportError:
- from urllib.request import urlopen
- from urllib.request import build_opener, install_opener
- from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler
- from urllib.error import URLError, HTTPError
- def main():
- out = options["output"]
- wfs_url = options["url"]
- request_base = "REQUEST=GetFeature&SERVICE=WFS&VERSION=1.0.0"
- wfs_url += request_base
- if options["name"]:
- wfs_url += "&TYPENAME=" + options["name"]
- if options["srs"]:
- wfs_url += "&SRS=" + options["srs"]
- if options["maximum_features"]:
- wfs_url += "&MAXFEATURES=" + options["maximum_features"]
- if int(options["maximum_features"]) < 1:
- # GTC Invalid WFS maximum features parameter
- grass.fatal(_("Invalid maximum number of features"))
- if options["start_index"]:
- wfs_url += "&STARTINDEX=" + options["start_index"]
- if int(options["start_index"]) < 1:
- # GTC Invalid WFS start index parameter
- grass.fatal(_('Features begin with index "1"'))
- if flags["r"]:
- bbox = grass.read_command("g.region", flags="w").split("=")[1]
- wfs_url += "&BBOX=" + bbox
- if flags["l"]:
- wfs_url = options["url"] + "REQUEST=GetCapabilities&SERVICE=WFS&VERSION=1.0.0"
- tmp = grass.tempfile()
- tmpxml = tmp + ".xml"
- grass.debug(wfs_url)
- # Set user and password if given
- if options["username"] and options["password"]:
- grass.message(_("Setting username and password..."))
- if os.path.isfile(options["username"]):
- with open(options["username"]) as f:
- filecontent = f.read()
- user = filecontent.strip()
- elif options["username"] in os.environ:
- user = os.environ[options["username"]]
- else:
- user = options["username"]
- if os.path.isfile(options["password"]):
- with open(options["password"]) as f:
- filecontent = f.read()
- pw = filecontent.strip()
- elif options["password"] in os.environ:
- pw = os.environ[options["password"]]
- else:
- pw = options["password"]
- passmgr = HTTPPasswordMgrWithDefaultRealm()
- passmgr.add_password(None, wfs_url, user, pw)
- authhandler = HTTPBasicAuthHandler(passmgr)
- opener = build_opener(authhandler)
- install_opener(opener)
- # GTC Downloading WFS features
- grass.message(_("Retrieving data..."))
- try:
- inf = urlopen(wfs_url)
- except HTTPError as e:
- # GTC WFS request HTTP failure
- grass.fatal(
- _("The server couldn't fulfill the request.\nError code: %s") % e.code
- )
- except URLError as e:
- # GTC WFS request network failure
- grass.fatal(_("Failed to reach the server.\nReason: %s") % e.reason)
- outf = open(tmpxml, "wb")
- while True:
- s = inf.read()
- if not s:
- break
- outf.write(s)
- inf.close()
- outf.close()
- if flags["l"]:
- import shutil
- if os.path.exists("wms_capabilities.xml"):
- grass.fatal(_('A file called "wms_capabilities.xml" already exists here'))
- # os.move() might fail if the temp file is on another volume, so we copy instead
- shutil.copy(tmpxml, "wms_capabilities.xml")
- try_remove(tmpxml)
- sys.exit(0)
- grass.message(_("Importing data..."))
- try:
- grass.run_command("v.in.ogr", flags="o", input=tmpxml, output=out)
- grass.message(_("Vector map <%s> imported from WFS.") % out)
- except Exception:
- grass.message(_("WFS import failed"))
- finally:
- try_remove(tmpxml)
- if __name__ == "__main__":
- options, flags = grass.parser()
- main()
|