Ejemplo n.º 1
0
def searchBasemaps(text, token):
    searchUrl = "{}/basemaps?version={}".format(pluginSetting("connectEndpoint"), pluginSetting("apiVersion"))

    headers = {}
    headers["Authorization"] = "Bearer {}".format(token)

    nam = NetworkAccessManager()
    res, content = nam.request(searchUrl, headers=headers)
    try:
        j = json.loads(content)
    except:
        raise Exception("Unable to parse server reply.")

    maps = [l for l in j if basemaputils.isSupported(l)]

    results = []
    if text == '':
        for item in maps:
            results.append(
                ConnectBasemap(item["endpoint"],
                               item["name"],
                               item["description"],
                               item,
                               item["accessList"]))
    else:
        for item in maps:
            if text.lower() in item["name"].lower() or text.lower() in item["description"].lower():
                results.append(
                    ConnectBasemap(item["endpoint"],
                                   item["name"],
                                   item["description"],
                                   item,
                                   item["accessList"]))

    return results
Ejemplo n.º 2
0
 def test_syncNAM_success(self):
     """Test NAM in sync mode."""
     # test success
     nam = NetworkAccessManager(debug=True)
     (response, content) = nam.request(self.serverUrl + '/get')
     self.assertTrue(response.ok)
     self.assertEqual(response.status_code, 200)
Ejemplo n.º 3
0
def search(text, category='', page=0, token=None):
    if text != '':
        text = '&q=' + text
        searchUrl = "{}/search/?version={}".format(pluginSetting("connectEndpoint"), pluginSetting("apiVersion"))
    else:
        searchUrl = "{}/search/matchAll?version={}".format(pluginSetting("connectEndpoint"), pluginSetting("apiVersion"))

    headers = {}
    headers["Authorization"] = "Bearer {}".format(token)

    nam = NetworkAccessManager()
    if category == '':
        res, content = nam.request("{}{}&si={}&c={}".format(searchUrl, text, int(page), RESULTS_PER_PAGE), headers=headers)
    else:
        res, content = nam.request("{}{}&cat={}&si={}&c={}".format(searchUrl, text, category, int(page), RESULTS_PER_PAGE), headers=headers)

    j = json.loads(re.sub(r'[^\x00-\x7f]',r'', content))
    results = []
    for element in j["features"]:
        props = element["properties"]
        roles = props["role"].split(",")
        category = props["category"]
        if category != "PLUG":
            title = props["title"] or props["description"].split(".")[0]
            if category in categories:
                results.append(categories[category][0](props["url"].replace("\n", ""),
                                                        title,
                                                        props["description"],
                                                        roles))
        else:
            plugin = _plugins.get(props["title"], None)
            if plugin:
                results.append(ConnectPlugin(plugin, roles))
    return results
Ejemplo n.º 4
0
    def test_AsyncNAM_tiff_success(self):
        """Test NAM in async mode with binary files to check for bytearray conversion."""
        # test success
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertTrue(httpResult.ok)
                # No status code in offline
                #self.assertEqual(httpResult.status_code, 200)
                self.assertEqual(httpResult.content,
                                 open(tiff_file, 'rb').read(), "Image differs")
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        tiff_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                 'data', '1.1.01.tiff')
        nam = NetworkAccessManager(debug=True)
        (response, content) = nam.request("file://%s" % tiff_file,
                                          blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 5
0
def getToken(login, password):
    global token
    if token:
        return token

    token = None

    payload = {"username": login,
               "password": password}

    headers = {}
    headers["Content-Type"] = "application/json"

    url = "{}/token?version={}".format(pluginSetting("connectEndpoint"), pluginSetting("apiVersion"))

    nam = NetworkAccessManager()
    try:
        res, data = nam.request(url, method="POST", body=json.dumps(payload), headers=headers)
    except Exception as e:
        return token

    try:
        responce = json.loads(str(data))
        token = responce["token"]
    except:
        pass

    return token
Ejemplo n.º 6
0
    def test_AsyncNAM_abort(self):
        """Test ANAM if it can manages abort during connection"""
        from threading import Timer

        # connection redirection
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertIn('Operation canceled', str(httpResult.exception))
                self.assertIsInstance(httpResult.exception,
                                      RequestsExceptionUserAbort)
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True)
        nam.request(self.serverUrl + '/delay/5', blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        # abort after 1sec
        t = Timer(1, nam.abort)
        t.start()
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 7
0
 def test_syncNAM_local_timeout(self):
     # test url timeout by client timout
     self.timeoutOriginal = self.settings.value(self.timeoutEntry)
     self.settings.setValue(self.timeoutEntry, 1000)
     nam = NetworkAccessManager(debug=True)
     with self.assertRaises(RequestsExceptionTimeout):
         (response, content) = nam.request(self.serverUrl + '/delay/60')
     self.settings.setValue(self.timeoutEntry, self.timeoutOriginal)
def appSDKification(folder, progress):
    ''' zip app folder and send to WAB compiler to apply SDK compilation.
    The returned zip will be the official webapp
    '''
    progress.oscillate()

    progress.setText("Get Authorization token")
    try:
        global __appSDKification_doAgain
        if __appSDKification_doAgain:
            QgsMessageLog.logMessage("Renew token in case of it is expired and retry", level=QgsMessageLog.WARNING)
            utils.resetCachedToken()
        token = utils.getToken()
    except Exception as e:
        pub.sendMessage(utils.topics.endAppSDKification, success=False, reason=str(e))
        return

    # zip folder to send for compiling
    progress.setText("Preparing data to compile")
    zipFileName = tempFilenameInTempFolder("webapp.zip", "webappbuilder")
    try:
        with zipfile.ZipFile(zipFileName, "w") as zf:
            relativeFrom = os.path.dirname(folder)
            for dirname, subdirs, files in os.walk(folder):
                # exclude data folder
                if 'data' in subdirs:
                    subdirs.remove('data')
                if relativeFrom in dirname:
                    zf.write(dirname, dirname[len(relativeFrom):])
                for filename in files:
                    fiename = os.path.join(dirname, filename)
                    zf.write(fiename, fiename[len(relativeFrom):])
    except:
        msg = "Could not zip webapp folder: {}".format(folder)
        pub.sendMessage(utils.topics.endAppSDKification, success=False, reason=msg)
        return

    # prepare data for WAB compiling request
    with open(zipFileName, 'rb') as f:
        fileContent = f.read()
    fields = { 'file': (os.path.basename(zipFileName), fileContent) }
    payload, content_type = encode_multipart_formdata(fields)

    headers = {}
    headers["authorization"] = "Bearer {}".format(token)
    headers["Content-Type"] = content_type

    # prepare request (as in NetworkAccessManager) but without blocking request
    # do http post
    progress.setText("Wait compilation")

    global __anam
    if __anam:
        del __anam
        __anam = None
    __anam = NetworkAccessManager(debug=pluginSetting("logresponse"))
    __anam.request(utils.wabCompilerUrl(), method='POST', body=payload, headers=headers, blocking=False)
    __anam.reply.finished.connect( lambda: manageFinished(__anam, zipFileName, folder, progress) )
Ejemplo n.º 9
0
 def test_syncNAM_unathorised(self):
     # connection refused http 401
     try:
         nam = NetworkAccessManager(debug=True)
         (response, content) = nam.request(self.serverUrl + '/status/401')
     except RequestsException as ex:
         self.assertTrue('Host requires authentication' in str(ex))
     except Exception as ex:
         raise ex
Ejemplo n.º 10
0
 def test_syncNAM_forbidden(self):
     # connection refused http 403
     try:
         nam = NetworkAccessManager(debug=True)
         (response, content) = nam.request(self.serverUrl + '/status/403')
     except RequestsException as ex:
         self.assertTrue('server replied: FORBIDDEN' in str(ex))
     except Exception as ex:
         raise ex
Ejemplo n.º 11
0
 def test_syncNAM_url_not_found(self):
     # test Url not found
     try:
         nam = NetworkAccessManager(debug=True)
         (response,
          content) = nam.request(self.serverUrl + '/somethingwrong')
     except RequestsException as ex:
         self.assertTrue('server replied: NOT FOUND' in str(ex))
     except Exception as ex:
         raise ex
Ejemplo n.º 12
0
    def test_syncNAM_customException(self):
        """Test NAM raise custom exception."""

        # test success
        class customEx(Exception):
            pass

        with self.assertRaises(customEx):
            nam = NetworkAccessManager(debug=True, exception_class=customEx)
            (response,
             content) = nam.request(self.serverUrl + '/somethingwrong')
Ejemplo n.º 13
0
 def __init__(self, service_url, authid, cache_time):
     # Do not call parent constructor, this is a patching class
     self.authid = authid
     self.cache_time = cache_time
     self.service_url = service_url.strip("/")
     self._cache = dict()
     self._version = None
     self.nam = NetworkAccessManager(self.authid,
                                     exception_class=FailedRequestError,
                                     debug=False)
     self.username = ''
     self.password = ''
Ejemplo n.º 14
0
 def test_syncNAM_tiff_success(self):
     """Test NAM in sync mode with binary files to check for bytearray conversion."""
     # test success
     nam = NetworkAccessManager(debug=True)
     tiff_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                              'data', '1.1.01.tiff')
     # Online
     #(response, content) = nam.request("http://sipi.usc.edu/database/download.php?vol=textures&img=1.1.01")
     # Offline (I tested and they give the same result)
     (response, content) = nam.request("file://%s" % tiff_file)
     self.assertTrue(response.ok)
     # Offline has no status code
     #self.assertEqual(response.status_code, 200)
     self.assertEqual(content,
                      open(tiff_file, 'rb').read(), "Image differs")
Ejemplo n.º 15
0
 def __init__(self, url, authid):
     self.service_url = url
     self.authid = authid
     if self.service_url.endswith("/"):
         self.service_url = self.service_url.strip("/")
     self.http = NetworkAccessManager(self.authid,
                                      exception_class=FailedRequestError)
 def getLegendSymbols(self, layer, ilayer, legendFolder):
     size = self._parameters["size"]
     qsize = QSize(size, size)
     symbols = []
     def appendSymbol(title, href):
         symbols.append({'title': title, 'href':href})
     if layer.type() == layer.VectorLayer:
         renderer = layer.rendererV2()
         if isinstance(renderer, QgsSingleSymbolRendererV2):
                 img = renderer.symbol().asImage(qsize)
                 symbolPath = os.path.join(legendFolder, "%i_0.png" % (ilayer))
                 img.save(symbolPath)
                 appendSymbol("",  os.path.basename(symbolPath))
         elif isinstance(renderer, QgsCategorizedSymbolRendererV2):
             for isymbol, cat in enumerate(renderer.categories()):
                 img = cat.symbol().asImage(qsize)
                 symbolPath = os.path.join(legendFolder, "%i_%i.png" % (ilayer, isymbol))
                 img.save(symbolPath)
                 appendSymbol(cat.label(), os.path.basename(symbolPath))
         elif isinstance(renderer, QgsGraduatedSymbolRendererV2):
             for isymbol, ran in enumerate(renderer.ranges()):
                 img = ran.symbol().asImage(qsize)
                 symbolPath = os.path.join(legendFolder, "%i_%i.png" % (ilayer, isymbol))
                 img.save(symbolPath)
                 appendSymbol("%s-%s" % (ran.lowerValue(), ran.upperValue()), os.path.basename(symbolPath))
         elif isinstance(renderer, QgsRuleBasedRendererV2):
             for isymbol, rule in enumerate(renderer.rootRule().children()):
                 img = rule.symbol().asImage(qsize)
                 symbolPath = os.path.join(legendFolder, "%i_%i.png" % (ilayer, isymbol))
                 img.save(symbolPath)
                 appendSymbol(rule.label(), os.path.basename(symbolPath))
     elif layer.type() == layer.RasterLayer:
         if layer.providerType() == "wms":
             source = layer.source()
             layerName = re.search(r"layers=(.*?)(?:&|$)", source).groups(0)[0]
             url = re.search(r"url=(.*?)(?:&|$)", source).groups(0)[0]
             styles = re.search(r"styles=(.*?)(?:&|$)", source).groups(0)[0]
             fullUrl = ("%s?LAYER=%s&STYLES=%s&REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&WIDTH=%i&HEIGHT=%i"
                        % (url, layerName, styles, size, size))
             nam = NetworkAccessManager(debug=pluginSetting("logresponse"))
             response, content = nam.request(fullUrl)
             symbolPath = os.path.join(legendFolder, "%i_0.png" % ilayer)
             with open(symbolPath, 'wb') as f:
                 f.write(content)
             appendSymbol("", os.path.basename(symbolPath))
     return symbols
def availableMaps(maps_uri, token):
    """Fetch the list of available maps from BCS endpoint,
    apparently this API method does not require auth"""
    # For testing purposes, we can also access to a json file directly
    if not maps_uri.startswith('http') or token is None:
        j = json.load(open(maps_uri))
    else:
        headers = {}
        headers["Authorization"] = "Bearer {}".format(token)

        nam = NetworkAccessManager()
        res, content = nam.request(maps_uri, headers=headers)
        try:
            j = json.loads(content)
        except:
            raise Exception("Unable to parse server reply.")

    return [l for l in j if isSupported(l)]
Ejemplo n.º 18
0
    def test_AsyncNAM_success(self):
        """Test ANAM if it can manages success."""
        # test success
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertTrue(httpResult.ok)
                self.assertEqual(httpResult.status_code, 200)
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True)
        nam.request(self.serverUrl + '/get', blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 19
0
    def test_AsyncNAM_forbidden(self):
        """Test ANAM if it can manages 403 (forbidden)"""
        # connection refused http 403
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertIn('server replied: FORBIDDEN',
                              str(httpResult.exception))
                self.assertIsInstance(httpResult.exception, RequestsException)
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True)
        nam.request(self.serverUrl + '/status/403', blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 20
0
    def test_AsyncNAM_url_not_found(self):
        """Test ANAM if it can manages 404"""
        # test Url not found
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertEqual(httpResult.status_code, 404)
                self.assertIn('server replied: NOT FOUND',
                              str(httpResult.exception))
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True)
        nam.request(self.serverUrl + '/somethingwrong', blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
def checkSDKServerVersion():
    localVersion = utils.sdkVersion()

    token = utils.getToken()

    headers = {}
    headers["authorization"] = "Bearer {}".format(token)

    nam = NetworkAccessManager(debug=pluginSetting("logresponse"))
    try:
        resp, text = nam.request(wabVersionUrl(), headers=headers)
    except Exception as e:
        # check if 401/403 => probably token expired
        permissionDenied = utils.isPermissionDenied(str(e))
        if not permissionDenied:
            raise e
        else:
            # renew token and try again
            utils.resetCachedToken()
            token = utils.getToken()

            # retry call
            headers["authorization"] = "Bearer {}".format(token)
            try:
                resp, text = nam.request(wabVersionUrl(), headers=headers)
            except Exception as e:
                # check if 401/403 => probably token expired
                permissionDenied = utils.isPermissionDenied(str(e))
                if not permissionDenied:
                    raise e
                else:
                    raise Exception(
                        "Permission denied with current Connect credentials")

    remoteVersion = json.loads(text)["boundless-sdk"]
    if localVersion != remoteVersion:
        raise VersionMismatchError(
            "The server SDK version (%s) is different from the expected version (%s)"
            % (remoteVersion, localVersion))
Ejemplo n.º 22
0
    def test_AsyncNAM_local_timeout(self):
        """Test ANAM if it can manages operation canceled by client."""
        """!!!Note!!! that finishedListener is emitted before than timeoutListener.
        When timeoutListener is called the httpResult has been changed to notify 
        timout."""
        # test url timeout by client timout
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertIn('Operation canceled', str(httpResult.exception))
                self.assertIsInstance(httpResult.exception, RequestsException)
            except Exception as ex:
                self.checkEx = ex

        def timeoutListener():
            try:
                httpResult = nam.httpResult()
                self.assertIn('Timeout error', str(httpResult.exception))
                self.assertIsInstance(httpResult.exception,
                                      RequestsExceptionTimeout)
            except Exception as ex:
                self.checkEx = ex

        self.timeoutOriginal = self.settings.value(self.timeoutEntry)
        self.settings.setValue(self.timeoutEntry, 1000)
        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True)
        nam.request(self.serverUrl + '/delay/60', blocking=False)
        QgsNetworkAccessManager.instance().requestTimedOut.connect(
            timeoutListener)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        self.settings.setValue(self.timeoutEntry, self.timeoutOriginal)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 23
0
    def test_AsyncNAM_redirect(self):
        """Test ANAM if it can manages url redirect"""
        # connection redirection
        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertIn('Host requires authentication',
                              str(httpResult.exception))
                self.assertIsInstance(httpResult.exception, RequestsException)
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True)
        nam.request(self.serverUrl + '/redirect-to?url=./status/401',
                    blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 24
0
    def test_AsyncNAM_customException(self):
        """Test ANAM raise curstom exception."""

        # test success
        class customEx(Exception):
            pass

        self.checkEx = None

        def finishedListener():
            try:
                httpResult = nam.httpResult()
                self.assertIsInstance(httpResult.exception, customEx)
            except Exception as ex:
                self.checkEx = ex

        loop = QtCore.QEventLoop()
        nam = NetworkAccessManager(debug=True, exception_class=customEx)
        nam.request(self.serverUrl + '/somethingwrong', blocking=False)
        nam.reply.finished.connect(finishedListener)
        nam.reply.finished.connect(loop.exit, QtCore.Qt.QueuedConnection)
        loop.exec_(flags=QtCore.QEventLoop.ExcludeUserInputEvents)
        if self.checkEx:
            raise self.checkEx
Ejemplo n.º 25
0
    def test_initNAM(self):
        """Test nam.__init__."""
        # default and init values
        initValueFor_http_call_result = Response({
            'status': 0,
            'status_code': 0,
            'status_message': '',
            'content': '',
            'ok': False,
            'headers': {},
            'reason': '',
            'exception': None,
        })

        nam = NetworkAccessManager()
        self.assertEqual(nam.disable_ssl_certificate_validation, False)
        self.assertEqual(nam.authid, None)
        self.assertEqual(nam.reply, None)
        self.assertEqual(nam.debug, True)
        self.assertEqual(nam.exception_class, None)
        self.assertEqual(nam.reply, None)
        self.assertEqual(nam.on_abort, False)
        self.assertEqual(nam.blocking_mode, False)
        self.assertEqual(nam.httpResult(), initValueFor_http_call_result)

        # passed values
        authid = '1234567'
        exception_class = Exception()
        nam = NetworkAccessManager(authid=authid,
                                   disable_ssl_certificate_validation=True,
                                   exception_class=exception_class,
                                   debug=False)
        self.assertEqual(nam.disable_ssl_certificate_validation, True)
        self.assertEqual(nam.authid, authid)
        self.assertEqual(nam.debug, False)
        self.assertEqual(nam.exception_class, exception_class)
Ejemplo n.º 26
0
class AuthCatalog(BaseCatalog):
    def __init__(self, service_url, authid, cache_time):
        # Do not call parent constructor, this is a patching class
        self.authid = authid
        self.cache_time = cache_time
        self.service_url = service_url.strip("/")
        self._cache = dict()
        self._version = None
        self.nam = NetworkAccessManager(self.authid,
                                        exception_class=FailedRequestError,
                                        debug=False)
        self.username = ''
        self.password = ''

    def http_request(self, url, data=None, method='get', headers={}):
        resp, content = self.nam.request(url, method, data, headers)
        return resp

    def setup_connection(self):
        pass
Ejemplo n.º 27
0
class what3words(object):
    """what3words API"""
    def __init__(self, host='api.what3words.com', apikey=''):
        self.host = 'https://' + host
        self.apikey = apikey
        self.nam = NetworkAccessManager()

    def forwardGeocode(self, words='index.home.raft', lang='en'):
        if isinstance(words, list):
            words = "%s.%s.%s" % (words[0], words[1], words[2])
        params = {
            'addr': words,
            'display': 'full',
            'format': 'json',
            'lang': lang
        }
        return self.postRequest(self.host + '/v2/forward', params)

    def reverseGeocode(self, lat='', lng='', corners='false', lang='en'):
        coords = "%s,%s" % (lat, lng)
        params = {
            'coords': coords,
            'display': 'full',
            'format': 'json',
            'lang': lang
        }
        return self.postRequest(self.host + '/v2/reverse', params)

    def getLanguages(self):
        return self.postRequest(self.host + '/v2/languages', dict())

    def postRequest(self, url, params):
        params.update({'key': self.apikey})
        encparams = urllib.parse.urlencode(params)
        url = url + '?' + encparams
        r, data = self.nam.request(url)
        return json.loads(data)
Ejemplo n.º 28
0
 def __init__(self, host='api.what3words.com', apikey=''):
     self.host = 'https://' + host
     self.apikey = apikey
     self.nam = NetworkAccessManager()
def checkAppCanBeCreated(appdef, forPreview=False):
    ##viewCrs = appdef["Settings"]["App view CRS"]
    jsonp = appdef["Settings"]["Use JSONP for WFS connections"]
    problems = []
    layers = appdef["Layers"]

    widgets = appdef["Widgets"].values()
    for w in widgets:
        w.checkProblems(appdef, problems, forPreview)

    themeModule = importlib.import_module("webappbuilder.themes." +
                                          appdef["Settings"]["Theme"])
    themeModule.checkProblems(appdef, problems)

    def getSize(lyr):
        ptsInFeature = 1 if lyr.geometryType(
        ) == QGis.Point else 10  #quick estimate...
        return lyr.featureCount() * (ptsInFeature + lyr.pendingFields().size())

    MAXSIZE = 30000
    for applayer in layers:
        if applayer.layer.type(
        ) == applayer.layer.VectorLayer and applayer.layer.providerType(
        ).lower() != "wfs":
            if getSize(applayer.layer) > MAXSIZE:
                problems.append(
                    "Layer %s might be too big for being loaded directly from a file."
                    % applayer.layer.name())

    nam = NetworkAccessManager(debug=pluginSetting("logresponse"))
    for applayer in layers:
        layer = applayer.layer
        if layer.providerType().lower() == "wms":
            try:
                source = layer.source()
                url = re.search(
                    r"url=(.*?)(?:&|$)",
                    source).groups(0)[0] + "?REQUEST=GetCapabilities"
                r, content = run(
                    lambda: nam.request(url, headers={"origin": "null"}))
                cors = r.headers.get("Access-Control-Allow-Origin", "").lower()
                if cors not in ["null", "*"]:
                    problems.append(
                        "Server for layer %s is not allowed to accept cross-origin requests."
                        " Popups and printing might not work correctly for that layer."
                        % layer.name())
            except:
                QgsMessageLog.logMessage(
                    "Warning: cannot verify cross-origin configuration for layer '%s'."
                    % layer.name(),
                    level=QgsMessageLog.WARNING)

    for applayer in layers:
        layer = applayer.layer
        if layer.providerType().lower() == "wfs":
            datasourceUri = QgsDataSourceURI(layer.source())
            url = datasourceUri.param("url") or layer.source().split("?")[0]
            url = url + "?service=WFS&version=1.1.0&REQUEST=GetCapabilities"
            try:
                if jsonp:
                    r, content = run(lambda: nam.request(url))
                    if "text/javascript" not in r.headers.values():
                        problems.append(
                            "Server for layer %s does not support JSONP. WFS layer won't be correctly loaded in Web App."
                            % layer.name())
                else:
                    r, content = run(
                        lambda: nam.request(url, headers={"origin": "null"}))
                    cors = r.headers.get("Access-Control-Allow-Origin",
                                         "").lower()
                    if cors not in ["null", "*"]:
                        problems.append(
                            "Server for layer %s is not allowed to accept cross-origin requests."
                            % layer.name())
            except:
                QgsMessageLog.logMessage(
                    "Warning: cannot verify if WFS layer server has the required configuration. Layer: '%s'."
                    % layer.name(),
                    level=QgsMessageLog.WARNING)

        if layer.type() != layer.VectorLayer:
            continue
        renderer = applayer.layer.rendererV2()
        allowed = [
            QgsSingleSymbolRendererV2, QgsCategorizedSymbolRendererV2,
            QgsGraduatedSymbolRendererV2, QgsHeatmapRenderer,
            QgsRuleBasedRendererV2
        ]
        try:
            allowed.append(QgsNullSymbolRenderer)
        except:
            pass
        if not isinstance(renderer, tuple(allowed)):
            problems.append(
                "Symbology used by layer %s includes unsupported elements."
                "Only single symbol, categorized, graduated, heatmap and rule-based renderers are supported."
                "This layer will not be correctly styled in the web app." %
                layer.name())
        if isinstance(renderer, QgsRuleBasedRendererV2):
            rules = renderer.rootRule().children()
            for rule in rules:
                expr = rule.filterExpression()
                unsupported = is_expression_supported(expr)
                if unsupported:
                    problems.append(
                        "The expression '%s' has unsupported functions: %s" %
                        (expr, ", ".join(unsupported)))

        if layer.hasLabelsEnabled():
            problems.append(
                "Layer %s uses old-style labeling. Labels might not be correctly rendered in the web app."
                % layer.name())
        if str(layer.customProperty("labeling/enabled")).lower() == "true":
            if unicode(layer.customProperty(
                    "labeling/isExpression")).lower() == "true":
                expr = layer.customProperty("labeling/fieldName")
                unsupported = is_expression_supported(expr)
                if unsupported:
                    problems.append(
                        "The expression '%s' has unsupported functions: %s" %
                        (expr, ", ".join(unsupported)))

    #TODO: check that layers using time attributes are not published using WMS

    hasTimeInfo = False
    for applayer in layers:
        if applayer.timeInfo is not None:
            hasTimeInfo = True
            break

    if hasTimeInfo and "timeline" not in appdef["Widgets"]:
        problems.append(
            "There are layers with time information, but timeline widget is not used."
        )

    if "timeline" in appdef["Widgets"]:
        for applayer in layers:
            layer = applayer.layer
            if layer.providerType().lower() == "wms":
                try:
                    source = layer.source()
                    url = re.search(r"url=(.*?)(?:&|$)", source).groups(0)[0]
                    layernames = re.search(r"layers=(.*?)(?:&|$)",
                                           source).groups(0)[0]
                    r, content = nam.request(
                        url + "?service=WMS&request=GetCapabilities")
                    root = ET.fromstring(
                        re.sub('\\sxmlns="[^"]+"', '', r.content))
                    for layerElement in root.iter('Layer'):
                        name = layerElement.find("Name").text
                        if name == layernames:
                            # look for discrete values
                            time = layerElement.find('Extent')
                            if time is not None:
                                applayer.timeInfo = time
                                hasTimeInfo = True
                            # look for interval values
                            time = layerElement.find('Dimension')
                            if time is not None and time.attrib[
                                    'name'] == 'time':
                                applayer.timeInfo = '"{}"'.format(time.text)
                                hasTimeInfo = True

                except:
                    #we swallow error, since this is not a vital info to add, so the app can still be created.
                    pass

        if not hasTimeInfo:
            problems.append(
                "Timeline widget is used but there are no layers with time information"
            )

    return problems
Ejemplo n.º 30
0
 def test_AsyncNAM_emptyreturn(self):
     """Test ANAM return value."""
     loop = QtCore.QEventLoop()
     nam = NetworkAccessManager(debug=True)
     ret = nam.request('anyurl', blocking=False)
     self.assertEqual(ret, (None, None))