Exemplo n.º 1
0
    def _open_url(self,
                  url_base,
                  data=None,
                  method='Get',
                  cookies=None,
                  username=None,
                  password=None,
                  timeout=30,
                  headers=None):
        headers = headers if headers is not None else {}
        kwargs = dict(timeout=timeout)

        kwargs['auth'] = self.auth

        method = method.split("}")[-1]

        if method.lower() == 'post':
            try:
                _ = etree.fromstring(data)
                headers['Content-Type'] = 'text/xml'
            except (ParseError, UnicodeEncodeError):
                pass

            kwargs['data'] = data

        elif method.lower() == 'get':
            kwargs['params'] = data

        else:
            raise ValueError(
                "Unknown method ('%s'), expected 'get' or 'post'" % method)

        if cookies is not None:
            kwargs['cookies'] = cookies

        req = requests.request(method.upper(),
                               url_base,
                               headers=headers,
                               **kwargs)

        if req.status_code in [400, 401]:
            raise ServiceException(req.text)

        if req.status_code in [404]:  # add more if needed
            req.raise_for_status()

        if 'Content-Type' in req.headers and req.headers['Content-Type'] in [
                'text/xml', 'application/xml'
        ]:
            se_tree = etree.fromstring(req.content)
            serviceException = se_tree.find(
                '{http://www.opengis.net/ows}Exception')
            if serviceException is None:
                serviceException = se_tree.find('ServiceException')
            if serviceException is not None:
                raise ServiceException(str(serviceException.text).strip())

        return ResponseWrapper(req)
Exemplo n.º 2
0
    def __init__(self, url, version='1.1.1', xml=None, username=None, password=None,
                 parse_remote_metadata=False, headers=None, timeout=30, auth=None):
        """Initialize."""
        if auth:
            if username:
                auth.username = username
            if password:
                auth.password = password
        self.url = url
        self.version = version
        self.timeout = timeout
        self.headers = headers
        self._capabilities = None
        self.auth = auth or Authentication(username, password)

        # Authentication handled by Reader
        reader = WMSCapabilitiesReader(
            self.version, url=self.url, headers=headers, auth=self.auth)
        if xml:  # read from stored xml
            self._capabilities = reader.readString(xml)
        else:  # read from server
            self._capabilities = reader.read(self.url, timeout=self.timeout)

        self.request = reader.request

        # avoid building capabilities metadata if the
        # response is a ServiceExceptionReport
        se = self._capabilities.find('ServiceException')
        if se is not None:
            err_message = str(se.text).strip()
            raise ServiceException(err_message)

        # build metadata objects
        self._buildMetadata(parse_remote_metadata)
Exemplo n.º 3
0
    def __init__(self,
                 url,
                 version=None,
                 xml=None,
                 username=None,
                 password=None,
                 parse_remote_metadata=False,
                 headers=None,
                 timeout=config_loader(dataset="WMS_request_timeout"),
                 auth=None):
        """Initialize."""

        if auth:
            if username:
                auth.username = username
            if password:
                auth.password = password
        self.url = url
        self.version = version
        self.timeout = timeout
        self.headers = headers
        self._capabilities = None
        self.auth = auth or Authentication(username, password)

        # Authentication handled by Reader
        reader = WMSCapabilitiesReader(self.version,
                                       url=self.url,
                                       headers=headers,
                                       auth=self.auth)
        if xml:
            # read from stored xml
            self._capabilities = reader.readString(xml)
        else:
            # read from server
            self._capabilities = reader.read(self.url, timeout=self.timeout)

        self.request = reader.request
        if not self.version:
            self.version = self._capabilities.attrib["version"]
            if self.version not in ["1.1.1", "1.3.0"]:
                self.version = "1.1.1"
            reader.version = self.version

        self.WMS_NAMESPACE = "{http://www.opengis.net/wms}" if self.version == "1.3.0" else ""
        self.OGC_NAMESPACE = "{http://www.opengis.net/ogc}" if self.version == "1.3.0" else ""

        # avoid building capabilities metadata if the
        # response is a ServiceExceptionReport
        se = self._capabilities.find('ServiceException')
        if se is not None:
            err_message = str(se.text).strip()
            raise ServiceException(err_message)

        # (mss) Store capabilities document.
        self.capabilities_document = reader.capabilities_document
        # (mss)

        # build metadata objects
        self._buildMetadata(parse_remote_metadata)
Exemplo n.º 4
0
    def Subgetmap_url(self,
                      layers=None,
                      styles=None,
                      srs=None,
                      bbox=None,
                      format=None,
                      size=None,
                      time=None,
                      transparent=False,
                      bgcolor='#FFFFFF',
                      exceptions='application/vnd.ogc.se_xml',
                      method='Get',
                      timeout=None,
                      **kwargs):
        try:
            base_url = next((m.get('url')
                             for m in self.getOperationByName('GetMap').methods
                             if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url
        request = {'version': self.version, 'request': 'GetMap'}

        request = self.__build_getmap_request(layers=layers,
                                              styles=styles,
                                              srs=srs,
                                              bbox=bbox,
                                              format=format,
                                              size=size,
                                              time=time,
                                              transparent=transparent,
                                              bgcolor=bgcolor,
                                              exceptions=exceptions,
                                              **kwargs)

        data = urlencode(request)
        ##########
        #Replace + with %20
        ##########
        data = data.replace("+", "%20")
        request = bind_url(base_url) + data

        # GetMap validity
        u = openURL(base_url,
                    data,
                    method,
                    username=self.username,
                    password=self.password,
                    timeout=timeout or self.timeout)
        # check for service exceptions, and return
        if u.info()['Content-Type'].split(';')[0] in [
                'application/vnd.ogc.se_xml'
        ]:
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = six.text_type(
                se_tree.find('ServiceException').text).strip()
            raise ServiceException(err_message)
        return request
Exemplo n.º 5
0
 def getcapabilities(self):
     """ Request and return capabilities document from the WMS as a
         file-like object.
         NOTE: this is effectively redundant now
     """
     reader = WMSCapabilitiesReader(self.version, url=self.url, un=self.username, pw=self.password)
     u = self._open(reader.capabilities_url(self.url))
     # check for service exceptions, and return
     if u.info().gettype() == 'application/vnd.ogc.se_xml':
         se_xml = u.read()
         se_tree = etree.fromstring(se_xml)
         err_message = str(se_tree.find('ServiceException').text).strip()
         raise ServiceException(err_message, se_xml)
     return u
Exemplo n.º 6
0
 def getcapabilities(self):
     """ Request and return capabilities document from the WMS as a
         file-like object.
         NOTE: this is effectively redundant now
     """
     reader = WMSCapabilitiesReader(self.version,
                                    url=self.url,
                                    auth=self.auth)
     u = self._open(reader.capabilities_url(self.url))
     # check for service exceptions, and return
     if u.info()['Content-Type'] == 'application/vnd.ogc.se_xml':
         se_xml = u.read()
         se_tree = etree.fromstring(se_xml)
         err_message = str(
             se_tree.find(
                 f'{self.OGC_NAMESPACE}ServiceException').text).strip()
         raise ServiceException(err_message, se_xml)
     return u
Exemplo n.º 7
0
    def __init__(self,
                 url,
                 version=None,
                 xml=None,
                 username=None,
                 password=None,
                 parse_remote_metadata=False,
                 timeout=30,
                 headers=None):
        """initialize"""
        self.url = url
        self.username = username
        self.password = password
        self.version = version
        self.timeout = timeout
        self.headers = headers
        self._capabilities = None

        # Authentication handled by Reader
        # Check whether required parameters (service, version, request) exist. If not, the missing parameters will be added.
        reader = SubWMSCapabilitiesReader(self.version,
                                          url=self.url,
                                          un=self.username,
                                          pw=self.password,
                                          headers=headers)
        if xml:  # read from stored xml
            self._capabilities = reader.readString(xml)
        else:  # read from server
            self._capabilities = reader.read(self.url, timeout=self.timeout)

        self.request = reader.request

        # avoid building capabilities metadata if the
        # response is a ServiceExceptionReport
        if subcommon.WMSExceptionDetection(self._capabilities):
            raise ServiceException("ServiceException")

        # build metadata objects
        self._buildMetadata(parse_remote_metadata)
 def __init__(self,
              url,
              credentials=Credentials(),
              cached_ows_services=None,
              logger=None,
              timeout=30):
     (username, password) = credentials.getFromUrl(url)
     if logger is not None:
         self.logger = logger
     else:
         self.logger = logging.getLogger("cswquerier")
         self.logger.addHandler(logging.NullHandler())
     self.owsServices = cached_ows_services or CachedOwsServices(
         credentials=credentials, timeout=timeout)
     try:
         self.csw = CatalogueServiceWeb(url,
                                        username=username,
                                        password=password)
     except BaseException as ex:
         raise ServiceException(ex)
     self.mds_not_parsable = []
     self.reset()
Exemplo n.º 9
0
    def getfeature(self, typename=None, filter=None, bbox=None, featureid=None,
                   featureversion=None, propertyname='*', maxfeatures=None,
                   srsname=None, outputFormat=None, method='Get',
                   startindex=None, sortby=None):
        """Request and return feature data as a file-like object.

        Parameters
        ----------
        typename : list
            List of typenames (string)
        filter : string
            XML-encoded OGC filter expression.
        bbox : tuple
            (left, bottom, right, top) in the feature type's coordinates.
        featureid : list
            List of unique feature ids (string)
        featureversion : string
            Default is most recent feature version.
        propertyname : list
            List of feature property names. '*' matches all.
        maxfeatures : int
            Maximum number of features to be returned.
        method : string
            Qualified name of the HTTP DCP method to use.
        srsname: string
            EPSG code to request the data in
        outputFormat: string (optional)
            Requested response format of the request.
        startindex: int (optional)
            Start position to return feature set (paging in combination with maxfeatures)
        sortby: list (optional)
            List of property names whose values should be used to order
            (upon presentation) the set of feature instances that
            satify the query.

        There are 3 different modes of use

        1) typename and bbox (simple spatial query). It is assumed, that
            bbox coordinates are given *always* in the east,north order
        2) typename and filter (more expressive)
        3) featureid (direct access to known features)
        """
        try:
            base_url = next((m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url
        request = {'service': 'WFS', 'version': self.version, 'request': 'GetFeature'}

        if not isinstance(typename, list):
            typename = [typename]

        if srsname is not None:
            request['srsname'] = str(srsname)

            # Check, if desired SRS is supported by the service for each
            # typename. Warning will be thrown if that SRS is not allowed."
            for name in typename:
                _ = self.getSRS(srsname, name)

        # check featureid
        if featureid:
            request['featureid'] = ','.join(featureid)

        # bbox
        elif bbox and typename:
            request["bbox"] = self.getBBOXKVP(bbox, typename)

        # or filter
        elif filter and typename:
            request['filter'] = str(filter)

        assert len(typename) > 0
        request['typename'] = ','.join(typename)

        if propertyname is not None:
            if not isinstance(propertyname, list):
                propertyname = [propertyname]
            request['propertyname'] = ','.join(propertyname)

        if sortby is not None:
            if not isinstance(sortby, list):
                sortby = [sortby]
            request['sortby'] = ','.join(sortby)

        if featureversion is not None:
            request['featureversion'] = str(featureversion)
        if maxfeatures is not None:
            request['maxfeatures'] = str(maxfeatures)
        if startindex is not None:
            request['startindex'] = str(startindex)
        if outputFormat is not None:
            request["outputFormat"] = outputFormat

        data = urlencode(request)
        log.debug("Making request: %s?%s" % (base_url, data))
        u = openURL(base_url, data, method, timeout=self.timeout, auth=self.auth)

        # check for service exceptions, rewrap, and return
        # We're going to assume that anything with a content-length > 32k
        # is data. We'll check anything smaller.
        if 'Content-Length' in u.info():
            length = int(u.info()['Content-Length'])
            have_read = False
        else:
            data = u.read()
            have_read = True
            length = len(data)

        if length < 32000:
            if not have_read:
                data = u.read()

            try:
                tree = etree.fromstring(data)
            except BaseException:
                # Not XML
                return self._makeStringIO(data)
            else:
                if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]:
                    se = tree.find(nspath_eval('ServiceException', namespaces["ogc"]))
                    raise ServiceException(str(se.text).strip())
                else:
                    return self._makeStringIO(data)
        else:
            if have_read:
                return self._makeStringIO(data)
            return u
Exemplo n.º 10
0
    def getfeatureinfo(self,
                       layers=None,
                       styles=None,
                       srs=None,
                       bbox=None,
                       format=None,
                       size=None,
                       time=None,
                       elevation=None,
                       dimensions={},
                       transparent=False,
                       bgcolor='#FFFFFF',
                       exceptions='XML',
                       query_layers=None,
                       xy=None,
                       info_format=None,
                       feature_count=20,
                       method='Get',
                       timeout=None,
                       **kwargs):
        try:
            base_url = next(
                (m.get('url')
                 for m in self.getOperationByName('GetFeatureInfo').methods
                 if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url

        # GetMap-Request
        request = self.__build_getmap_request(layers=layers,
                                              styles=styles,
                                              srs=srs,
                                              bbox=bbox,
                                              dimensions=dimensions,
                                              elevation=elevation,
                                              format=format,
                                              size=size,
                                              time=time,
                                              transparent=transparent,
                                              bgcolor=bgcolor,
                                              exceptions=exceptions,
                                              kwargs=kwargs)

        # extend to GetFeatureInfo-Request
        request['request'] = 'GetFeatureInfo'

        if not query_layers:
            __str_query_layers = ','.join(layers)
        else:
            __str_query_layers = ','.join(query_layers)

        request['query_layers'] = __str_query_layers
        request['i'] = str(xy[0])
        request['j'] = str(xy[1])
        request['info_format'] = info_format
        request['feature_count'] = str(feature_count)

        data = urlencode(request)

        self.request = bind_url(base_url) + data

        u = openURL(base_url,
                    data,
                    method,
                    username=self.username,
                    password=self.password,
                    timeout=timeout or self.timeout)

        # check for service exceptions, and return
        if u.info()['Content-Type'] == 'XML':
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = six.text_type(
                se_tree.find('ServiceException').text).strip()
            raise ServiceException(err_message)
        return u
Exemplo n.º 11
0
    def getmap(self,
               layers=None,
               styles=None,
               srs=None,
               bbox=None,
               format=None,
               size=None,
               time=None,
               elevation=None,
               dimensions={},
               transparent=False,
               bgcolor='#FFFFFF',
               exceptions='XML',
               method='Get',
               timeout=None,
               **kwargs):
        """Request and return an image from the WMS as a file-like object.

        Parameters
        ----------
        layers : list
            List of content layer names.
        styles : list
            Optional list of named styles, must be the same length as the
            layers list.
        srs : string
            A spatial reference system identifier.
            Note: this is an invalid query parameter key for 1.3.0 but is being
                  retained for standardization with 1.1.1.
            Note: throws exception if the spatial ref is ESRI's "no reference"
                  code (EPSG:0)
        bbox : tuple
            (left, bottom, right, top) in srs units (note, this order does not
                change depending on axis order of the crs).

            CRS:84: (long, lat)
            EPSG:4326: (lat, long)
        format : string
            Output image format such as 'image/jpeg'.
        size : tuple
            (width, height) in pixels.

        time : string or list or range
            Optional. Time value of the specified layer as ISO-8601 (per value)
        elevation : string or list or range
            Optional. Elevation value of the specified layer.
        dimensions: dict (dimension : string or list or range)
            Optional. Any other Dimension option, as specified in the GetCapabilities

        transparent : bool
            Optional. Transparent background if True.
        bgcolor : string
            Optional. Image background color.
        method : string
            Optional. HTTP DCP method name: Get or Post.
        **kwargs : extra arguments
            anything else e.g. vendor specific parameters

        Example
        -------
            wms = WebMapService('http://webservices.nationalatlas.gov/wms/1million',\
                                    version='1.3.0')
            img = wms.getmap(layers=['airports1m'],\
                                 styles=['default'],\
                                 srs='EPSG:4326',\
                                 bbox=(-176.646, 17.7016, -64.8017, 71.2854),\
                                 size=(300, 300),\
                                 format='image/jpeg',\
                                 transparent=True)
            out = open('example.jpg.jpg', 'wb')
            out.write(img.read())
            out.close()

        """

        try:
            base_url = next((m.get('url')
                             for m in self.getOperationByName('GetMap').methods
                             if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url

        request = self.__build_getmap_request(layers=layers,
                                              styles=styles,
                                              srs=srs,
                                              bbox=bbox,
                                              dimensions=dimensions,
                                              elevation=elevation,
                                              format=format,
                                              size=size,
                                              time=time,
                                              transparent=transparent,
                                              bgcolor=bgcolor,
                                              exceptions=exceptions,
                                              **kwargs)

        data = urlencode(request)

        self.request = bind_url(base_url) + data

        u = openURL(base_url,
                    data,
                    method,
                    username=self.username,
                    password=self.password,
                    timeout=timeout or self.timeout)

        # need to handle casing in the header keys
        headers = {}
        for k, v in six.iteritems(u.info()):
            headers[k.lower()] = v

        # handle the potential charset def
        if headers['content-type'].split(';')[0] in [
                'application/vnd.ogc.se_xml', 'text/xml'
        ]:
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = six.text_type(
                se_tree.find(nspath('ServiceException',
                                    OGC_NAMESPACE)).text).strip()
            raise ServiceException(err_message)
        return u
Exemplo n.º 12
0
    def getfeature(self,
                   typename=None,
                   filter=None,
                   bbox=None,
                   featureid=None,
                   featureversion=None,
                   propertyname=['*'],
                   maxfeatures=None,
                   srsname=None,
                   outputFormat=None,
                   method='Get',
                   timeout=None):
        """Request and return feature data as a file-like object.

        Parameters
        ----------
        typename : list
            List of typenames (string)
        filter : string
            XML-encoded OGC filter expression.
        bbox : tuple
            (left, bottom, right, top) in the feature type's coordinates.
        featureid : list
            List of unique feature ids (string)
        featureversion : string
            Default is most recent feature version.
        propertyname : list
            List of feature property names. '*' matches all.
        maxfeatures : int
            Maximum number of features to be returned.
        method : string
            Qualified name of the HTTP DCP method to use.
        srsname: string
            EPSG code to request the data in
        outputFormat: string (optional)
            Requested response format of the request.
        timeout : number
            A timeout value (in seconds) for the request.

        There are 3 different modes of use

        1) typename and bbox (simple spatial query). It is assumed, that
            bbox coordinates are given *always* in the east,north order
        2) typename and filter (more expressive)
        3) featureid (direct access to known features)
        """
        if timeout:
            to = timeout
        else:
            to = self.timeout
        try:
            base_url = next(
                (m.get('url')
                 for m in self.getOperationByName('GetFeature').methods
                 if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url
        request = {
            'service': 'WFS',
            'version': self.version,
            'request': 'GetFeature'
        }

        if not isinstance(typename, list):
            typename = [typename]

        if srsname is not None:
            # check, if desired SRS is supported by the service for this typename
            if typename is not None:
                # convert srsname string to Crs object found in GetCaps
                srsnameobj = self.getSRS(srsname, typename[0])
                if srsnameobj is not None:
                    request['srsname'] = srsnameobj.id
                else:
                    options = ", ".join(
                        map(lambda x: x.id,
                            self.contents[typename[0]].crsOptions))
                    raise ServiceException(
                        "SRSNAME %s not supported.  Options: %s" %
                        (srsname, options))
            else:
                request['srsname'] = str(srsname)

        # check featureid
        if featureid:
            request['featureid'] = ','.join(featureid)

        # bbox
        elif bbox and typename:
            request["bbox"] = self.getBBOXKVP(bbox, typename)

        # or filter
        elif filter and typename:
            request['filter'] = str(filter)

        assert len(typename) > 0
        request['typename'] = ','.join(typename)

        if propertyname is not None:
            if not isinstance(propertyname, list):
                propertyname = [propertyname]
            request['propertyname'] = ','.join(propertyname)

        if featureversion is not None:
            request['featureversion'] = str(featureversion)
        if maxfeatures is not None:
            request['maxfeatures'] = str(maxfeatures)
        if outputFormat is not None:
            request["outputFormat"] = outputFormat

        data = urlencode(request)
        log.debug("Making request: %s?%s" % (base_url, data))
        u = openURL(base_url, data, method, timeout=to)

        # check for service exceptions, rewrap, and return
        # We're going to assume that anything with a content-length > 32k
        # is data. We'll check anything smaller.
        try:
            length = int(u.info()['Content-Length'])
            have_read = False
        except (KeyError, AttributeError):
            data = u.read()
            have_read = True
            length = len(data)

        if length < 32000:
            if not have_read:
                data = u.read()

            try:
                tree = etree.fromstring(data)
            except BaseException:
                # Not XML
                return StringIO(data)
            else:
                if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]:
                    se = tree.find(
                        nspath_eval('ServiceException', namespaces["ogc"]))
                    raise ServiceException(str(se.text).strip())
                else:
                    return StringIO(data)
        else:
            if have_read:
                return StringIO(data)
            return u
Exemplo n.º 13
0
    def Subgetmap_url(self,
                      layers=None,
                      styles=None,
                      srs=None,
                      bbox=None,
                      format=None,
                      size=None,
                      time=None,
                      elevation=None,
                      dimensions={},
                      transparent=False,
                      bgcolor='#FFFFFF',
                      exceptions='XML',
                      method='Get',
                      timeout=None,
                      **kwargs):

        try:
            base_url = next((m.get('url')
                             for m in self.getOperationByName('GetMap').methods
                             if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url

        request = self.__build_getmap_request(layers=layers,
                                              styles=styles,
                                              srs=srs,
                                              bbox=bbox,
                                              dimensions=dimensions,
                                              elevation=elevation,
                                              format=format,
                                              size=size,
                                              time=time,
                                              transparent=transparent,
                                              bgcolor=bgcolor,
                                              exceptions=exceptions,
                                              **kwargs)

        data = urlencode(request)
        data = data.replace("+", "%20")

        request = bind_url(base_url) + data

        u = openURL(base_url,
                    data,
                    method,
                    username=self.username,
                    password=self.password,
                    timeout=timeout or self.timeout)

        # need to handle casing in the header keys
        headers = {}
        for k, v in six.iteritems(u.info()):
            headers[k.lower()] = v

        # handle the potential charset def
        if headers['content-type'].split(';')[0] in [
                'application/vnd.ogc.se_xml', 'text/xml'
        ]:
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = six.text_type(
                se_tree.find(
                    subcommon.nspath('ServiceException',
                                     OGC_NAMESPACE)).text).strip()
            raise ServiceException(err_message)
        return request
Exemplo n.º 14
0
    def getmap(self, layers=None, styles=None, srs=None, bbox=None,
               format=None, size=None, time=None, transparent=False,
               bgcolor='#FFFFFF',
               exceptions='application/vnd.ogc.se_xml',
               method='Get',
               timeout=None,
               **kwargs
               ):
        """Request and return an image from the WMS as a file-like object.

        Parameters
        ----------
        layers : list
            List of content layer names.
        styles : list
            Optional list of named styles, must be the same length as the
            layers list.
        srs : string
            A spatial reference system identifier.
        bbox : tuple
            (left, bottom, right, top) in srs units.
        format : string
            Output image format such as 'image/jpeg'.
        size : tuple
            (width, height) in pixels.
        transparent : bool
            Optional. Transparent background if True.
        bgcolor : string
            Optional. Image background color.
        method : string
            Optional. HTTP DCP method name: Get or Post.
        **kwargs : extra arguments
            anything else e.g. vendor specific parameters

        Example
        -------
            wms = WebMapService('http://giswebservices.massgis.state.ma.us/geoserver/wms', version='1.1.1')
            img = wms.getmap(layers=['massgis:GISDATA.SHORELINES_ARC'],\
                                 styles=[''],\
                                 srs='EPSG:4326',\
                                 bbox=(-70.8, 42, -70, 42.8),\
                                 size=(300, 300),\
                                 format='image/jpeg',\
                                 transparent=True)
            out = open('example.jpg', 'wb')
            bytes_written = out.write(img.read())
            out.close()

        """
        try:
            base_url = next((m.get('url') for m in self.getOperationByName('GetMap').methods if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url
        request = {'version': self.version, 'request': 'GetMap'}

        request = self.__build_getmap_request(
            layers=layers,
            styles=styles,
            srs=srs,
            bbox=bbox,
            format=format,
            size=size,
            time=time,
            transparent=transparent,
            bgcolor=bgcolor,
            exceptions=exceptions,
            **kwargs)

        data = urlencode(request)

        self.request = bind_url(base_url) + data

        u = openURL(base_url, data, method, timeout=timeout or self.timeout, auth=self.auth)

        # check for service exceptions, and return
        if u.info().get('Content-Type', '').split(';')[0] in ['application/vnd.ogc.se_xml']:
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = six.text_type(se_tree.find('ServiceException').text).strip()
            raise ServiceException(err_message)
        return u
Exemplo n.º 15
0
    def getfeature(
        self,
        typename=None,
        filter=None,
        bbox=None,
        featureid=None,
        featureversion=None,
        propertyname="*",
        maxfeatures=None,
        srsname=None,
        outputFormat=None,
        method="{http://www.opengis.net/wfs}Get",
        startindex=None,
    ):
        """Request and return feature data as a file-like object.

        Parameters
        ----------
        typename : list
            List of typenames (string)
        filter : string
            XML-encoded OGC filter expression.
        bbox : tuple
            (left, bottom, right, top) in the feature type's coordinates.
        featureid : list
            List of unique feature ids (string)
        featureversion : string
            Default is most recent feature version.
        propertyname : list
            List of feature property names. '*' matches all.
        maxfeatures : int
            Maximum number of features to be returned.
        method : string
            Qualified name of the HTTP DCP method to use.
        srsname: string
            EPSG code to request the data in
        outputFormat: string (optional)
            Requested response format of the request.
        startindex: int (optional)
            Start position to return feature set (paging in combination with maxfeatures)


        There are 3 different modes of use

        1) typename and bbox (simple spatial query)
        2) typename and filter (more expressive)
        3) featureid (direct access to known features)
        """
        try:
            base_url = next(
                (m.get("url")
                 for m in self.getOperationByName("GetFeature").methods
                 if m.get("type").lower() == method.lower()))
        except StopIteration:
            base_url = self.url
        request = {
            "service": "WFS",
            "version": self.version,
            "request": "GetFeature"
        }

        # check featureid
        if featureid:
            request["featureid"] = ",".join(featureid)
        elif bbox and typename:
            request["bbox"] = ",".join([repr(x) for x in bbox])
        elif filter and typename:
            request["filter"] = str(filter)

        if srsname:
            request["srsname"] = str(srsname)

        assert len(typename) > 0
        request["typename"] = ",".join(typename)

        if propertyname is not None:
            if not isinstance(propertyname, list):
                propertyname = [propertyname]
            request["propertyname"] = ",".join(propertyname)

        if featureversion:
            request["featureversion"] = str(featureversion)
        if maxfeatures:
            request["maxfeatures"] = str(maxfeatures)
        if startindex:
            request["startindex"] = str(startindex)

        if outputFormat is not None:
            request["outputFormat"] = outputFormat

        data = urlencode(request)
        log.debug("Making request: %s?%s" % (base_url, data))
        u = openURL(base_url,
                    data,
                    method,
                    timeout=self.timeout,
                    auth=self.auth)

        # check for service exceptions, rewrap, and return
        # We're going to assume that anything with a content-length > 32k
        # is data. We'll check anything smaller.

        if "Content-Length" in u.info():
            length = int(u.info()["Content-Length"])
            have_read = False
        else:
            data = u.read()
            have_read = True
            length = len(data)

        if length < 32000:
            if not have_read:
                data = u.read()

            try:
                tree = etree.fromstring(data)
            except BaseException:
                # Not XML
                return makeStringIO(data)
            else:
                if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE:
                    se = tree.find(nspath("ServiceException", OGC_NAMESPACE))
                    raise ServiceException(str(se.text).strip())
                else:
                    return makeStringIO(data)
        else:
            if have_read:
                return makeStringIO(data)
            return u
Exemplo n.º 16
0
    def getlegendgraphic(self,
                         layer=None,
                         styles=None,
                         format=None,
                         size=None,
                         time=None,
                         transparent=False,
                         bgcolor='#FFFFFF',
                         exceptions='application/vnd.ogc.se_xml',
                         method='Get',
                         timeout=None,
                         **kwargs):
        # Extract legend url from layer styles
        request = None
        request = self.contents[layer].getlegendgraphicrequest()

        # Construct legend url
        if request is None:
            try:
                base_url = next((m.get('url') for m in self.getOperationByName(
                    'GetLegendGraphic').methods
                                 if m.get('type').lower() == method.lower()))
            except StopIteration:
                base_url = self.url
            request = {'version': self.version, 'request': 'GetLegendGraphic'}

            request = self.__build_getlegendgraphic_request(
                layer=layer,
                styles=styles,
                format=format,
                size=size,
                time=time,
                transparent=transparent,
                bgcolor=bgcolor,
                exceptions=exceptions,
                **kwargs)

            data = urlencode(request)
            ##########
            #Replace + with %20
            ##########
            data = data.replace("+", "%20")

            request = bind_url(base_url) + data

        u = openURL(request,
                    method,
                    username=self.username,
                    password=self.password,
                    timeout=timeout or self.timeout)

        # check for service exceptions, and return
        if u.info()['Content-Type'].split(';')[0] in [
                'application/vnd.ogc.se_xml'
        ]:
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = six.text_type(
                se_tree.find('ServiceException').text).strip() + request
            raise ServiceException(err_message)
        return u, request
Exemplo n.º 17
0
    def getmap(self,
               layers=None,
               styles=None,
               srs=None,
               bbox=None,
               format=None,
               size=None,
               time=None,
               transparent=False,
               bgcolor='#FFFFFF',
               exceptions='application/vnd.ogc.se_xml',
               method='Get'):
        """Request and return an image from the WMS as a file-like object.

        Parameters
        ----------
        layers : list
            List of content layer names.
        styles : list
            Optional list of named styles, must be the same length as the
            layers list.
        srs : string
            A spatial reference system identifier.
        bbox : tuple
            (left, bottom, right, top) in srs units.
        format : string
            Output image format such as 'image/jpeg'.
        size : tuple
            (width, height) in pixels.
        transparent : bool
            Optional. Transparent background if True.
        bgcolor : string
            Optional. Image background color.
        method : string
            Optional. HTTP DCP method name: Get or Post.

        Example
        -------
            >>> img = wms.getmap(layers=['global_mosaic'],
            ...                  styles=['visual'],
            ...                  srs='EPSG:4326',
            ...                  bbox=(-112,36,-106,41),
            ...                  format='image/jpeg',
            ...                  size=(300,250),
            ...                  transparent=True,
            ...                  )
            >>> out = open('example.jpg', 'wb')
            >>> out.write(img.read())
            >>> out.close()

        """
        base_url = self.getOperationByName('GetMap').methods[method]['url']
        request = {'version': self.version, 'request': 'GetMap'}

        # check layers and styles
        assert len(layers) > 0
        request['layers'] = ','.join(layers)
        if styles:
            assert len(styles) == len(layers)
            request['styles'] = ','.join(styles)
        else:
            request['styles'] = ''

        # size
        request['width'] = str(size[0])
        request['height'] = str(size[1])

        request['srs'] = str(srs)
        request['bbox'] = ','.join([str(x) for x in bbox])
        request['format'] = str(format)
        request['transparent'] = str(transparent).upper()
        request['bgcolor'] = '0x' + bgcolor[1:7]
        request['exceptions'] = str(exceptions)

        if time is not None:
            request['time'] = str(time)

        data = urlencode(request)
        proxies = config_loader(dataset="proxies")
        u = openURL(base_url,
                    data,
                    method,
                    username=self.username,
                    password=self.password,
                    proxies=proxies)

        # check for service exceptions, and return
        if u.info()['Content-Type'] == 'application/vnd.ogc.se_xml':
            se_xml = u.read()
            se_tree = etree.fromstring(se_xml)
            err_message = str(se_tree.find('ServiceException').text).strip()
            raise ServiceException(err_message, se_xml)
        return u
Exemplo n.º 18
0
def openURL(url_base,
            data=None,
            method='Get',
            cookies=None,
            username=None,
            password=None,
            timeout=config_loader(dataset="WMS_request_timeout"),
            headers=None,
            proxies=None):
    # (mss) added proxies
    # (mss) timeout default of 30secs set by the config_loader
    """
    Function to open URLs.

    Uses requests library but with additional checks for OGC service exceptions and url formatting.
    Also handles cookies and simple user password authentication.
    """
    headers = headers if headers is not None else {}
    rkwargs = {}

    rkwargs['timeout'] = timeout

    auth = None
    if username and password:
        auth = (username, password)

    rkwargs['auth'] = auth

    # FIXUP for WFS in particular, remove xml style namespace
    # @TODO does this belong here?
    method = method.split("}")[-1]

    if method.lower() == 'post':
        try:
            etree.fromstring(data)
            headers['Content-Type'] = 'text/xml'
        except (ParseError, UnicodeEncodeError) as error:
            # (mss)
            logging.debug("ParseError, UnicodeEncodeError %s", error)

        rkwargs['data'] = data

    elif method.lower() == 'get':
        rkwargs['params'] = data

    else:
        raise ValueError(
            f"Unknown method ('{method}'), expected 'get' or 'post'")

    if cookies is not None:
        rkwargs['cookies'] = cookies

    req = requests.request(
        method.upper(),
        url_base,
        headers=headers,
        # MSS
        proxies=proxies,
        **rkwargs)

    if req.status_code in [400, 401]:
        raise ServiceException(req.text)

    if req.status_code in [404, 500, 502, 503, 504]:  # add more if needed
        req.raise_for_status()

    # check for service exceptions without the http header set
    if 'Content-Type' in req.headers and req.headers['Content-Type'] in [
            'text/xml', 'application/xml', 'application/vnd.ogc.se_xml',
            'application/vnd.ogc.wms_xml'
    ]:
        # just in case 400 headers were not set, going to have to read the xml to see if it's an exception report.
        se_tree = etree.fromstring(req.content)

        # to handle the variety of namespaces and terms across services
        # and versions, especially for "legacy" responses like WMS 1.3.0
        possible_errors = [
            '{http://www.opengis.net/ows}Exception',
            '{http://www.opengis.net/ows/1.1}Exception',
            '{http://www.opengis.net/ogc}ServiceException', 'ServiceException'
        ]

        for possible_error in possible_errors:
            serviceException = se_tree.find(possible_error)
            if serviceException is not None:
                # and we need to deal with some message nesting
                raise ServiceException('\n'.join([
                    str(t).strip() for t in serviceException.itertext()
                    if str(t).strip()
                ]))

    return ResponseWrapper(req)
Exemplo n.º 19
0
    def getfeature(self,
                   typename=None,
                   filter=None,
                   bbox=None,
                   featureid=None,
                   featureversion=None,
                   propertyname=['*'],
                   maxfeatures=None,
                   srsname=None,
                   outputFormat=None,
                   method='{http://www.opengis.net/wfs}Get',
                   timeout=None):
        """Request and return feature data as a file-like object.
        
        Parameters
        ----------
        typename : list
            List of typenames (string)
        filter : string 
            XML-encoded OGC filter expression.
        bbox : tuple
            (left, bottom, right, top) in the feature type's coordinates.
        featureid : list
            List of unique feature ids (string)
        featureversion : string
            Default is most recent feature version.
        propertyname : list
            List of feature property names. '*' matches all.
        maxfeatures : int
            Maximum number of features to be returned.
        method : string
            Qualified name of the HTTP DCP method to use.
        srsname: string
            EPSG code to request the data in
        outputFormat: string (optional)
            Requested response format of the request.
        timeout : number
            A timeout value (in seconds) for the request.

            
        There are 3 different modes of use

        1) typename and bbox (simple spatial query)
        2) typename and filter (more expressive)
        3) featureid (direct access to known features)
        """
        if timeout:
            to = timeout
        else:
            to = self.timeout
        try:
            base_url = next(
                (m.get('url')
                 for m in self.getOperationByName('GetFeature').methods
                 if m.get('type').lower() == method.lower()))
        except StopIteration:
            base_url = self.url
        request = {
            'service': 'WFS',
            'version': self.version,
            'request': 'GetFeature'
        }

        # check featureid
        if featureid:
            request['featureid'] = ','.join(featureid)
        elif bbox and typename:
            request['bbox'] = ','.join([repr(x) for x in bbox])
        elif filter and typename:
            request['filter'] = str(filter)

        if srsname:
            request['srsname'] = str(srsname)

        assert len(typename) > 0
        request['typename'] = ','.join(typename)

        if propertyname:
            request['propertyname'] = ','.join(propertyname)
        if featureversion: request['featureversion'] = str(featureversion)
        if maxfeatures: request['maxfeatures'] = str(maxfeatures)

        if outputFormat is not None:
            request["outputFormat"] = outputFormat

        data = urlencode(request)
        log.debug("Making request: %s?%s" % (base_url, data))
        u = openURL(base_url, data, method, timeout=to)

        # check for service exceptions, rewrap, and return
        # We're going to assume that anything with a content-length > 32k
        # is data. We'll check anything smaller.

        try:
            length = int(u.info()['Content-Length'])
            have_read = False
        except (KeyError, AttributeError):
            data = u.read()
            have_read = True
            length = len(data)

        if length < 32000:
            if not have_read:
                data = u.read()

            try:
                tree = etree.fromstring(data)
            except BaseException:
                # Not XML
                return StringIO(data)
            else:
                if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE:
                    se = tree.find(nspath('ServiceException', OGC_NAMESPACE))
                    raise ServiceException(str(se.text).strip())
                else:
                    return StringIO(data)
        else:
            if have_read:
                return StringIO(data)
            return u