def test_zip_unzip(self): tmpDir = QTemporaryDir() tmpFile = "{}/project.qgz".format(tmpDir.path()) project = QgsProject() l0 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "points.shp"), "points", "ogr") l1 = QgsVectorLayer(os.path.join(TEST_DATA_DIR, "lines.shp"), "lines", "ogr") project.addMapLayers([l0, l1]) self.assertTrue(project.write(tmpFile)) project2 = QgsProject() self.assertFalse(project2.isZipped()) self.assertTrue(project2.fileName() == "") self.assertTrue(project2.read(tmpFile)) self.assertTrue(project2.isZipped()) self.assertTrue(project2.fileName() == tmpFile) layers = project2.mapLayers() self.assertEqual(len(layers.keys()), 2) self.assertTrue(layers[l0.id()].isValid(), True) self.assertTrue(layers[l1.id()].isValid(), True) project2.clear() self.assertFalse(project2.isZipped())
def test_wmts_document_cache(client): """ Test getcapabilites response """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Delete document project = QgsProject() project.setFileName(client.getprojectpath("france_parts.qgs").strpath) # Get project document root path docroot = cachefilter._cache.get_documents_root(project.fileName()) cachefilter.deleteCachedDocuments(project) assert not os.path.exists(docroot.as_posix()) parameters = { 'MAP': project.fileName(), 'REQUEST': 'GetCapabilities', 'SERVICE': 'WMTS' } # Get the cached path from the request parameters docpath = cachefilter._cache.get_document_cache( project.fileName(), parameters, '.xml' ).as_posix() assert not os.path.exists(docpath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(docpath) original_content = rv.content # Make a second request and check for header rv = client.get(qs, project.fileName()) assert rv.status_code == 200 assert rv.headers.get('X-Qgis-Debug-Cache-Plugin') == 'wmtsCacheServer' assert rv.headers.get('X-Qgis-Debug-Cache-Path') == docpath cached_content = rv.content assert original_content == cached_content
def _to_json(key: str, project: QgsProject): return dict( key=key, filename=project.fileName(), last_modified=project.lastModified().toString(Qt.ISODate), num_layers=project.count(), )
def make_temp_qgis_file(project: QgsProject) -> str: project_backup_dir = tempfile.mkdtemp() original_filename = project.fileName() backup_filename = os.path.join(project_backup_dir, f"{project.baseName()}.qgs") project.write(backup_filename) project.setFileName(original_filename) return backup_filename
def get(self, query: str, project: str=None) -> _Response: """ Return server response from query """ request = QgsBufferServerRequest(query, QgsServerRequest.GetMethod, {}, None) response = QgsBufferServerResponse() if project is not None and not os.path.isabs(project): projectpath = self.datapath.join(project) qgsproject = QgsProject() if not qgsproject.read(projectpath.strpath): raise ValueError("Error reading project '%s':" % projectpath.strpath) else: qgsproject = None # See https://github.com/qgis/QGIS/pull/9773 self.server.serverInterface().setConfigFilePath(qgsproject.fileName()) self.server.handleRequest(request, response, project=qgsproject) return _Response(response,request)
def transactional_project(iface, src_url=None, dest_url=None, dont_resolve_layers=True): """Context manager returning a ``QgsProject`` instance and saves it on exit if no error occured. If ``src_url`` is ``None``, the returned project is the current one (the one loaded int QGIS interface). Else, the project found at ``src_url`` is returned. The project is saved to its original location if ``dest_url`` is ``None``, else it is saved to ``dest_url``. Implementation detail: after saving the project with ``proj.write()`` (thus updating the project file on disk), when the user clicks on the Save icon in QGIS UI, a warning is shown indicating that the file has been modified after it has been opened by QGIS. Workaround: the project is reloaded with ``proj.clear()`` and ``proj.read()``. """ try: if src_url: proj = QgsProject() if dont_resolve_layers: proj.read(src_url, QgsProject.FlagDontResolveLayers) else: proj.read(src_url) else: proj = QgsProject.instance() yield proj except Exception as exc: log_exception(exc, level='Critical', feedback=True, iface=iface) finally: if not dest_url: project_saved = proj.write() dest_url = proj.fileName() else: project_saved = proj.write(dest_url) if not project_saved: log_message('Project has not been saved after transaction.', level='Warning', feedback=True, iface=iface) # XXX: better way to avoid warning if the user click save ? proj.clear() proj.read(dest_url)
def test_configpath(self): """ Test plugin can read confif path """ try: from qgis.server import QgsServerFilter from qgis.core import QgsProject except ImportError: print("QGIS Server plugins are not compiled. Skipping test") return d = unitTestDataPath('qgis_server_accesscontrol') + '/' self.projectPath = os.path.join(d, "project.qgs") self.server = QgsServer() # global to be modified inside plugin filters globals()['configFilePath2'] = None class Filter0(QgsServerFilter): """Body setter, clear body, keep headers""" def requestReady(self): global configFilePath2 configFilePath2 = self.serverInterface().configFilePath() serverIface = self.server.serverInterface() serverIface.registerFilter(Filter0(serverIface), 100) # Test using MAP self._execute_request('?service=simple&MAP=%s' % self.projectPath) # Check config file path self.assertEqual(configFilePath2, self.projectPath) # Reset result globals()['configFilePath2'] = None # Test with prqject as argument project = QgsProject() project.read(self.projectPath) self._execute_request_project('?service=simple', project=project) # Check config file path self.assertEqual(configFilePath2, project.fileName())
def get_project_summary(key: str, project: QgsProject): """ Return json summary for cached project """ def layer_summary(layer_id: str, layer: QgsMapLayer): return dict( id=layer_id, name=layer.name(), source=layer.publicSource(), crs=layer.crs().userFriendlyIdentifier(), valid=layer.isValid(), spatial=layer.isSpatial(), ) layers = [ layer_summary(idstr, l) for (idstr, l) in project.mapLayers().items() ] return dict(cache_key=key, filename=project.fileName(), bad_layers_count=sum(1 for ls in layers if not ls['valid']), layers=layers, crs=project.crs().userFriendlyIdentifier(), last_modified=project.lastModified().toString(Qt.ISODate))
def test_wmts_cachemngrapi_delete_docs(client): """ Test the API with to remove docs cache /wmtscache/collections /wmtscache/collection/(?<collectionId>[^/]+?)/docs """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Delete document project = QgsProject() project.setFileName(client.getprojectpath("france_parts.qgs").strpath) # Get project document root path docroot = cachefilter._cache.get_documents_root(project.fileName()) cachefilter.deleteCachedDocuments(project) assert not os.path.exists(docroot.as_posix()) parameters = { 'MAP': project.fileName(), 'REQUEST': 'GetCapabilities', 'SERVICE': 'WMTS' } # Get the cached path from the request parameters docpath = cachefilter._cache.get_document_cache(project.fileName(), parameters, '.xml').as_posix() assert not os.path.exists(docpath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(docpath) # Cache manager API requests qs = "/wmtscache/collections" rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'collections' in json_content assert len(json_content['collections']) == 1 collection = json_content['collections'][0] assert 'id' in collection assert 'links' in collection assert 'project' in collection assert collection['project'] == client.getprojectpath( "france_parts.qgs").strpath # Get docs info qs = "/wmtscache/collections/{}/docs".format(collection['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == collection['id'] assert 'project' in json_content assert json_content['project'] == client.getprojectpath( "france_parts.qgs").strpath assert 'documents' in json_content assert json_content['documents'] == 1 # Delete docs qs = "/wmtscache/collections/{}/docs".format(collection['id']) rv = client.delete(qs) assert rv.status_code == 200 # Get docs info qs = "/wmtscache/collections/{}/docs".format(collection['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == collection['id'] assert 'project' in json_content assert json_content['project'] == client.getprojectpath( "france_parts.qgs").strpath assert 'documents' in json_content assert json_content['documents'] == 0 # Test that document cache has been deleted assert not os.path.exists(docpath)
def _convert(self, project: QgsProject) -> None: project.baseName() xml_elements_to_preserve = {} on_original_project_read = self._on_original_project_read_wrapper( xml_elements_to_preserve) project.readProject.connect(on_original_project_read) if self.export_type == ExportType.Cable: # the `backup_filename` is copied right after packaging is requested. It has all the unsaved # project settings, which means they will be available in the packaged project too. project.read(self.backup_filename) elif self.export_type == ExportType.Cloud: # if you save the project without QGIS GUI, the project no longer has `theMapCanvas` canvas # so we should use the original project file that already has `theMapCanvas`. There is no # gain using the `backup_filename`, since there is no user to modify the project. project.read(project.fileName()) else: raise NotImplementedError( f"Unknown package type: {self.export_type}") project.readProject.disconnect(on_original_project_read) self.export_folder.mkdir(parents=True, exist_ok=True) self.total_progress_updated.emit(0, 100, self.trUtf8("Converting project…")) self.__layers = list(project.mapLayers().values()) # We store the pks of the original vector layers for layer in self.__layers: pk_names = None if layer.type() == QgsMapLayer.VectorLayer: pk_names = [] for idx in layer.primaryKeyAttributes(): pk_name = layer.fields()[idx].name() # and we check that the primary key fields names don't have a comma in the name if "," in pk_name: raise ValueError("Comma in field names not allowed") pk_names.append(pk_name) layer.setCustomProperty("QFieldSync/sourceDataPrimaryKeys", ",".join(pk_names)) layer_data: LayerData = { "id": layer.id(), "name": layer.name(), "type": layer.type(), "source": layer.source(), "fields": layer.fields() if hasattr(layer, "fields") else None, "pk_names": pk_names, } self.__layer_data_by_id[layer.id()] = layer_data self.__layer_data_by_name[layer.name()] = layer_data if self.create_basemap and self.project_configuration.create_base_map: self._export_basemap() # Loop through all layers and copy/remove/offline them copied_files = list() non_ascii_filename_layers: Dict[str, str] = {} non_utf8_encoding_layers: Dict[str, str] = {} for layer_idx, layer in enumerate(self.__layers): self.total_progress_updated.emit( layer_idx - len(self.__offline_layers), len(self.__layers), self.trUtf8("Copying layers…"), ) layer_source = LayerSource(layer) layer_action = (layer_source.action if self.export_type == ExportType.Cable else layer_source.cloud_action) if not layer.isValid(): project.removeMapLayer(layer) continue if not layer_source.is_supported: project.removeMapLayer(layer) continue if layer_source.is_file and not isascii(layer_source.filename): non_ascii_filename_layers[layer.name()] = layer_source.filename if layer_source.is_localized_path: continue if (layer.type() == QgsMapLayer.VectorLayer and layer.dataProvider() and layer.dataProvider().encoding() != "UTF-8" # some providers return empty string as encoding, just ignore them and layer.dataProvider().encoding() != ""): non_utf8_encoding_layers[ layer.name()] = layer.dataProvider().encoding() if layer_action == SyncAction.OFFLINE: if self.project_configuration.offline_copy_only_aoi: extent = QgsCoordinateTransform( QgsCoordinateReferenceSystem( self.area_of_interest_crs), layer.crs(), QgsProject.instance(), ).transformBoundingBox(self.area_of_interest.boundingBox()) layer.selectByRect(extent) if not layer.selectedFeatureCount(): layer.selectByIds([FID_NULL]) self.__offline_layers.append(layer) self.__offline_layer_names.append(layer.name()) elif (layer_action == SyncAction.COPY or layer_action == SyncAction.NO_ACTION): copied_files = layer_source.copy(self.export_folder, copied_files) elif layer_action == SyncAction.KEEP_EXISTENT: layer_source.copy(self.export_folder, copied_files, True) elif layer_action == SyncAction.REMOVE: project.removeMapLayer(layer) if non_ascii_filename_layers: layers = ", ".join([ f'"{name}" at "{path}"' for name, path in non_ascii_filename_layers.items() ]) message = self.tr( "Some layers are stored at file paths that are not ASCII encoded: {}. Working with paths that are not in ASCII might cause problems. It is highly recommended to rename them to ASCII encoded paths." ).format(layers) self.warning.emit(self.tr("QFieldSync"), message) if non_utf8_encoding_layers: layers = ", ".join([ f"{name} ({encoding})" for name, encoding in non_utf8_encoding_layers.items() ]) message = self.tr( "Some layers do not use UTF-8 encoding: {}. Working with layers that do not use UTF-8 encoding might cause problems. It is highly recommended to convert them to UTF-8 encoded layers." ).format(layers) self.warning.emit(self.tr("QFieldSync"), message) export_project_filename = self.export_folder.joinpath( f"{self.original_filename.stem}_qfield.qgs") # save the original project path self.project_configuration.original_project_path = str( self.original_filename) # save the offline project twice so that the offline plugin can "know" that it's a relative path QgsProject.instance().write(str(export_project_filename)) # export the DCIM folder copy_images( str(self.original_filename.parent.joinpath("DCIM")), str(export_project_filename.parent.joinpath("DCIM")), ) try: # Run the offline plugin for gpkg gpkg_filename = "data.gpkg" if self.__offline_layers: offline_layer_ids = [o_l.id() for o_l in self.__offline_layers] if not self.offline_editing.convertToOfflineProject( str(self.export_folder), gpkg_filename, offline_layer_ids, self.project_configuration.offline_copy_only_aoi, self.offline_editing.GPKG, None, ): raise Exception( self. tr("QGIS Offline editing error: failed to convert layers to offline layers" )) except AttributeError: # Run the offline plugin for spatialite spatialite_filename = "data.sqlite" if self.__offline_layers: offline_layer_ids = [o_l.id() for o_l in self.__offline_layers] if not self.offline_editing.convertToOfflineProject( str(self.export_folder), spatialite_filename, offline_layer_ids, self.project_configuration.offline_copy_only_aoi, self.offline_editing.SpatiaLite, None, ): raise Exception( self. tr("QGIS Offline editing error: failed to convert layers to offline layers" )) # Disable project options that could create problems on a portable # project with offline layers self.post_process_layers() # Now we have a project state which can be saved as offline project on_original_project_write = self._on_original_project_write_wrapper( xml_elements_to_preserve) project.writeProject.connect(on_original_project_write) QgsProject.instance().write(str(export_project_filename)) project.writeProject.disconnect(on_original_project_write)
def test_wmts_cachemngrapi_layerid_error(client): """ Test the API with empty cache /wmtscache/collection/(?<collectionId>[^/]+?) /wmtscache/collection/(?<collectionId>[^/]+?)/layers /wmtscache/collection/(?<collectionId>[^/]+?)/layers/(?<layerId>[^/]+?) """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Delete tiles project = QgsProject() project.setFileName(client.getprojectpath("france_parts.qgs").strpath) # Get project tiles root path tileroot = cachefilter._cache.get_tiles_root(project.fileName()) cachefilter.deleteCachedImages(project) assert not os.path.exists(tileroot.as_posix()) parameters = { "MAP": project.fileName(), "SERVICE": "WMTS", "VERSION": "1.0.0", "REQUEST": "GetTile", "LAYER": "france_parts", "STYLE": "", "TILEMATRIXSET": "EPSG:4326", "TILEMATRIX": "0", "TILEROW": "0", "TILECOL": "0", "FORMAT": "image/png" } # Get the cached path from the request parameters tilepath = cachefilter._cache.get_tile_cache(project.fileName(), parameters).as_posix() assert not os.path.exists(tilepath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) # original_content = rv.content if rv.status_code != 200: LOGGER.error(lxml.etree.tostring(rv.xml, pretty_print=True)) assert rv.status_code == 200 # Test that tile cache has been created assert os.path.exists(tilepath) # Cache manager API requests qs = "/wmtscache/collections" rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'collections' in json_content assert len(json_content['collections']) == 1 collection = json_content['collections'][0] assert 'id' in collection assert 'links' in collection assert 'project' in collection assert collection['project'] == client.getprojectpath( "france_parts.qgs").strpath # Get layers info qs = "/wmtscache/collections/{}/layers".format(collection['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == collection['id'] assert 'layers' in json_content assert len(json_content['layers']) == 1 qs = "/wmtscache/collections/{}/layers/{}".format(collection['id'], 'foobar') rv = client.delete(qs) assert rv.status_code == 404 json_content = json.loads(rv.content) assert 'error' in json_content assert json_content['error'].get('message') == "Layer 'foobar' not found"
def test_wmts_cachemngrapi_cache_info(client): """ Test the API with cache /wmtscache /wmtscache/collections /wmtscache/collection/(?<collectionId>[^/]+?) /wmtscache/collection/(?<collectionId>[^/]+?)/docs /wmtscache/collection/(?<collectionId>[^/]+?)/layers /wmtscache/collection/(?<collectionId>[^/]+?)/layers/(?<layerId>[^/]+?) """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Delete document project = QgsProject() project.setFileName(client.getprojectpath("france_parts.qgs").strpath) # Get project document root path docroot = cachefilter._cache.get_documents_root(project.fileName()) cachefilter.deleteCachedDocuments(project) assert not os.path.exists(docroot.as_posix()) parameters = { 'MAP': project.fileName(), 'REQUEST': 'GetCapabilities', 'SERVICE': 'WMTS' } # Get the cached path from the request parameters docpath = cachefilter._cache.get_document_cache(project.fileName(), parameters, '.xml').as_posix() assert not os.path.exists(docpath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(docpath) # Get project tiles root path tileroot = cachefilter._cache.get_tiles_root(project.fileName()) cachefilter.deleteCachedImages(project) assert not os.path.exists(tileroot.as_posix()) parameters = { "MAP": project.fileName(), "SERVICE": "WMTS", "VERSION": "1.0.0", "REQUEST": "GetTile", "LAYER": "france_parts", "STYLE": "", "TILEMATRIXSET": "EPSG:4326", "TILEMATRIX": "0", "TILEROW": "0", "TILECOL": "0", "FORMAT": "image/png" } # Get the cached path from the request parameters tilepath = cachefilter._cache.get_tile_cache(project.fileName(), parameters).as_posix() assert not os.path.exists(tilepath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) # original_content = rv.content if rv.status_code != 200: LOGGER.error(lxml.etree.tostring(rv.xml, pretty_print=True)) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(tilepath) # Cache manager API requests qs = "/wmtscache/collections" rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'cache_layout' in json_content assert json_content['cache_layout'] == 'tc' assert 'collections' in json_content assert len(json_content['collections']) == 1 assert 'links' in json_content assert len(json_content['links']) == 0 collection = json_content['collections'][0] assert 'id' in collection assert 'links' in collection assert 'project' in collection assert collection['project'] == client.getprojectpath( "france_parts.qgs").strpath qs = "/wmtscache/collections/{}".format(collection['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == collection['id'] assert 'project' in json_content assert json_content['project'] == client.getprojectpath( "france_parts.qgs").strpath assert 'links' in json_content assert len(json_content['links']) == 2 qs = "/wmtscache/collections/{}/docs".format(collection['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == collection['id'] assert 'project' in json_content assert json_content['project'] == client.getprojectpath( "france_parts.qgs").strpath assert 'documents' in json_content assert json_content['documents'] == 1 assert 'links' in json_content assert len(json_content['links']) == 0 qs = "/wmtscache/collections/{}/layers".format(collection['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == collection['id'] assert 'project' in json_content assert json_content['project'] == client.getprojectpath( "france_parts.qgs").strpath assert 'layers' in json_content assert len(json_content['layers']) == 1 assert 'links' in json_content assert len(json_content['links']) == 0 layer = json_content['layers'][0] assert 'id' in layer assert 'links' in layer qs = "/wmtscache/collections/{}/layers/{}".format(collection['id'], layer['id']) rv = client.get(qs) assert rv.status_code == 200 assert rv.headers.get('Content-Type', "").startswith('application/json') json_content = json.loads(rv.content) assert 'id' in json_content assert json_content['id'] == layer['id'] assert 'links' in json_content assert len(json_content['links']) == 0
def get_project_title(project: QgsProject) -> str: """ Gets project title, or if non available, the basename of the filename""" if project.title(): return project.title() else: return Path(project.fileName()).stem
def test_wmts_document_cache_time(client): """ Test getcapabilites response time """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Copy project shutil.copy( client.getprojectpath("france_parts.qgs"), client.getprojectpath("france_parts_copy.qgs") ) # Delete document project = QgsProject() project.setFileName(client.getprojectpath("france_parts_copy.qgs").strpath) # Get project document root path docroot = cachefilter._cache.get_documents_root(project.fileName()) cachefilter.deleteCachedDocuments(project) assert not os.path.exists(docroot.as_posix()) parameters = { 'MAP': project.fileName(), 'REQUEST': 'GetCapabilities', 'SERVICE': 'WMTS' } # Get the cached path from the request parameters docpath = cachefilter._cache.get_document_cache( project.fileName(), parameters, '.xml' ).as_posix() assert not os.path.exists(docpath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(docpath) # Get time of document cache creation docmtime = os.stat(docpath).st_mtime projmtime = project.lastModified().toMSecsSinceEpoch() / 1000.0 assert projmtime < docmtime project.write() projmtime = project.lastModified().toMSecsSinceEpoch() / 1000.0 assert projmtime > docmtime # Make a second request rv = client.get(qs, project.fileName()) assert rv.status_code == 200 ndocmtime = os.stat(docpath).st_mtime projmtime = project.lastModified().toMSecsSinceEpoch() / 1000.0 assert projmtime < ndocmtime assert docmtime < ndocmtime # Clean files after testing Path(client.getprojectpath("france_parts_copy.qgs")).unlink()
def test_wmts_document_tile(client): """ Test WMTS tile response """ plugin = client.getplugin('wmtsCacheServer') assert plugin is not None # Create a filter cachefilter = plugin.create_filter() # Delete document project = QgsProject() project.setFileName(client.getprojectpath("france_parts.qgs").strpath) # Get project document root path tileroot = cachefilter._cache.get_tiles_root(project.fileName()) cachefilter.deleteCachedImages(project) assert not os.path.exists(tileroot.as_posix()) parameters = { "MAP": project.fileName(), "SERVICE": "WMTS", "VERSION": "1.0.0", "REQUEST": "GetTile", "LAYER": "france_parts", "STYLE": "", "TILEMATRIXSET": "EPSG:4326", "TILEMATRIX": "0", "TILEROW": "0", "TILECOL": "0", "FORMAT": "image/png" } # Get the cached path from the request parameters tilepath = cachefilter._cache.get_tile_cache( project.fileName(), parameters ).as_posix() assert not os.path.exists(tilepath) # Make a request qs = "?" + "&".join("%s=%s" % item for item in parameters.items()) rv = client.get(qs, project.fileName()) original_content = rv.content if rv.status_code != 200: LOGGER.error(lxml.etree.tostring(rv.xml, pretty_print=True)) assert rv.status_code == 200 # Test that document cache has been created assert os.path.exists(tilepath) # Make a second request and check for header rv = client.get(qs, project.fileName()) assert rv.status_code == 200 assert rv.headers.get('X-Qgis-Debug-Cache-Plugin') == 'wmtsCacheServer' assert rv.headers.get('X-Qgis-Debug-Cache-Path') == tilepath cached_content = rv.content assert original_content == cached_content