def testDuplicatedLayerNamesInDifferentWorkSpaces(self): """ Test that when there are more than one layer with the same name they can be both added to QGIS """ return self.cat.catalog.create_workspace(WORKSPACEB, "http://testb.com") wsb = self.cat.catalog.get_workspaces(WORKSPACEB)[0] # Need to use prefixed names when retrieving pt1 = self.ws.name + ':' + PT1 pt1b = wsb.name + ':' + PT1 self.cat.publishLayer(PT1, self.ws, name=PT1) self.assertIsNotNone(self.cat.catalog.get_layer(pt1)) self.cat.addLayerToProject(pt1, pt1) layer = layers.resolveLayer(pt1) # Add second layer with the same name self.cat.publishLayer(PT1, wsb, name=PT1) self.assertIsNotNone(self.cat.catalog.get_layer(pt1b)) self.cat.addLayerToProject(pt1b, pt1b) layerb = layers.resolveLayer(pt1b) self.assertNotEqual(layer, layerb) # Check uris self.assertNotEqual(layer.publicSource(), layerb.publicSource()) self.assertNotEqual(QgsProject.instance().mapLayersByName(layer.name()), []) self.assertNotEqual(QgsProject.instance().mapLayersByName(layerb.name()), []) QgsProject.instance().removeMapLayer(layer.id()) QgsProject.instance().removeMapLayer(layerb.id()) self.cat.catalog.delete(self.cat.catalog.get_layer(pt1), recurse=True) self.cat.catalog.delete(self.cat.catalog.get_layer(pt1b), recurse=True)
def testPublishLayersDialog(self): pt1 = layers.resolveLayer(PT1) pt2 = layers.resolveLayer(PT2) dialog = PublishLayersDialog(self.catalogs, [pt1,pt2]) cancelWidget = dialog.buttonBox.button(dialog.buttonBox.Cancel) QTest.mouseClick(cancelWidget, Qt.LeftButton) self.assertIsNone(dialog.topublish) cat = self.catalogs.values()[0] for idx, ws in enumerate(cat.get_workspaces()): if ws.name == WORKSPACE: wsIdx = idx if ws.name == WORKSPACEB: wsIdxB = idx dialog = PublishLayersDialog(self.catalogs, [pt1,pt2]) self.assertEquals(1, dialog.table.columnCount()) self.assertEquals(2, dialog.table.rowCount()) dialog.table.cellWidget(0,0).setCurrentIndex(wsIdx) dialog.table.cellWidget(1,0).setCurrentIndex(wsIdxB) okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok) QTest.mouseClick(okWidget, Qt.LeftButton) self.assertIsNotNone(dialog.topublish) self.assertEquals(WORKSPACE, dialog.topublish[0][2].name) self.assertEquals(WORKSPACEB, dialog.topublish[1][2].name) dialog = PublishLayersDialog({"catalog": cat, "catalog2:": cat}, [pt1,pt2]) self.assertEquals(2, dialog.table.columnCount()) self.assertEquals(2, dialog.table.rowCount()) dialog.table.cellWidget(0,1).setCurrentIndex(wsIdx) dialog.table.cellWidget(1,1).setCurrentIndex(wsIdxB) okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok) QTest.mouseClick(okWidget, Qt.LeftButton) self.assertIsNotNone(dialog.topublish) self.assertEquals(WORKSPACE, dialog.topublish[0][2].name) self.assertEquals(WORKSPACEB, dialog.topublish[1][2].name)
def testUploadRenameAndDownload(self): QgsNetworkAccessManager.instance().cache().clear() self.cat.publishLayer(PT1, self.ws, name = PT1) self.assertIsNotNone(self.cat.catalog.get_layer(PT1)) self.cat.addLayerToProject(PT1, PT1 + "_fromGeoserver") layer = layers.resolveLayer(PT1 + "_fromGeoserver") self.cat.publishLayer(PT1, self.ws, name = PT1 + "b") self.cat.addLayerToProject(PT1 + "b", PT1 + "b_fromGeoserver") layer = layers.resolveLayer(PT1 + "b_fromGeoserver") self.cat.catalog.delete(self.cat.catalog.get_layer(PT1), recurse = True) self.cat.catalog.delete(self.cat.catalog.get_layer(PT1 + "b"), recurse = True)
def testUploadRenameAndDownload(self): QgsNetworkAccessManager.instance().cache().clear() self.cat.publishLayer(PT1, self.ws, name=PT1) self.assertIsNotNone(self.cat.catalog.get_layer(PT1)) self.cat.addLayerToProject(PT1, PT1 + "_fromGeoserver") layer = layers.resolveLayer(PT1 + "_fromGeoserver") self.cat.publishLayer(PT1, self.ws, name=PT1 + "b") self.cat.addLayerToProject(PT1 + "b", PT1 + "b_fromGeoserver") layer = layers.resolveLayer(PT1 + "b_fromGeoserver") self.cat.catalog.delete(self.cat.catalog.get_layer(PT1), recurse=True) self.cat.catalog.delete(self.cat.catalog.get_layer(PT1 + "b"), recurse=True)
def testRasterLayerRoundTrip(self): self.cat.publishLayer(DEM, self.ws, name = DEM) self.assertIsNotNone(self.cat.catalog.get_layer(DEM)) self.cat.addLayerToProject(DEM, DEM2) layer = layers.resolveLayer(DEM2) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.cat.catalog.delete(self.cat.catalog.get_layer(DEM), recurse = True)
def testVectorLayerRoundTrip(self): self.cat.publishLayer(PT1, self.ws, name = PT1) self.assertIsNotNone(self.cat.catalog.get_layer(PT1)) self.cat.addLayerToProject(PT1, PT1) layer = layers.resolveLayer(PT1) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.cat.catalog.delete(self.cat.catalog.get_layer(PT1), recurse = True)
def upload(self, layer, workspace=None, overwrite=True, name=None): '''uploads the specified layer''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) name = name if name is not None else layer.name() title = name name = name.replace(" ", "_") settings = QtCore.QSettings() restApi = bool( settings.value("/GeoServer/Settings/GeoServer/UseRestApi", True, bool)) if layer.type() not in (layer.RasterLayer, layer.VectorLayer): msg = layer.name() + ' is not a valid raster or vector layer' raise Exception(msg) provider = layer.dataProvider() try: if provider.name() == 'postgres': self._publishPostgisLayer(layer, workspace, overwrite, name) elif restApi: self._uploadRest(layer, workspace, overwrite, name) else: self._uploadImporter(layer, workspace, overwrite, name) except UploadError, e: msg = ('Could not save the layer %s, there was an upload ' 'error: %s' % (layer.name(), str(e))) e.args = (msg, ) raise
def upload(self, layer, workspace=None, overwrite=True, name=None): '''uploads the specified layer''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) name = name if name is not None else layer.name() title = name name = name.replace(" ", "_") settings = QtCore.QSettings() restApi = bool(settings.value("/GeoServer/Settings/GeoServer/UseRestApi", True, bool)) if layer.type() not in (layer.RasterLayer, layer.VectorLayer): msg = layer.name() + ' is not a valid raster or vector layer' raise Exception(msg) provider = layer.dataProvider() try: if provider.name() == 'postgres': self._publishPostgisLayer(layer, workspace, overwrite, name) elif restApi: self._uploadRest(layer, workspace, overwrite, name) else: self._uploadImporter(layer, workspace, overwrite, name) except UploadError, e: msg = ('Could not save the layer %s, there was an upload ' 'error: %s' % (layer.name(), str(e))) e.args = (msg,) raise
def testRasterLayerRoundTrip(self): self.cat.publishLayer(DEM, self.ws, name=DEM) self.assertIsNotNone(self.cat.catalog.get_layer(DEM)) self.cat.addLayerToProject(DEM, DEM2) layer = layers.resolveLayer(DEM2) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.cat.catalog.delete(self.cat.catalog.get_layer(DEM), recurse=True)
def testVectorLayerRoundTrip(self): self.cat.publishLayer(PT1, self.ws, name=PT1) self.assertIsNotNone(self.cat.catalog.get_layer(PT1)) self.cat.addLayerToProject(PT1, PT1) layer = layers.resolveLayer(PT1) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.cat.catalog.delete(self.cat.catalog.get_layer(PT1), recurse=True)
def testPreuploadVectorHook(self): if not catalog.processingOk: print 'skipping testPreuploadVectorHook, processing not installed' return settings = QSettings() oldHookFile = str( settings.value("/GeoServer/Settings/GeoServer/PreuploadVectorHook", "")) hookFile = os.path.join(os.path.dirname(__file__), "resources", "vector_hook.py") settings.setValue("/GeoServer/Settings/GeoServer/PreuploadVectorHook", hookFile) try: self.cat.publishLayer(PT1, self.ws, name=HOOK) self.assertIsNotNone(self.cat.catalog.get_layer(HOOK)) self.cat.addLayerToProject(HOOK) layer = layers.resolveLayer(HOOK) self.assertEqual(1, layer.featureCount()) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) finally: settings.setValue( "/GeoServer/Settings/GeoServer/PreuploadVectorHook", oldHookFile) self.cat.catalog.delete(self.cat.catalog.get_layer(HOOK), recurse=True)
def upload(self, layer, workspace=None, overwrite=True, name=None): '''uploads the specified layer''' if isinstance(layer, str): layer = layers.resolveLayer(layer) name = name or layer.name() title = name name = name.replace(" ", "_") if layer.type() not in (layer.RasterLayer, layer.VectorLayer): raise Exception(layer.name() + ' is not a valid raster or vector layer') provider = layer.dataProvider() try: if layer.type() == layer.RasterLayer: path = self.getDataFromLayer(layer) self.catalog.create_coveragestore(name, path=path, workspace=workspace) elif layer.type() == layer.VectorLayer: path = self.getDataFromLayer(layer) self.catalog.create_featurestore(name, data=path, workspace=workspace, overwrite=overwrite) except UploadError as e: raise Exception('Could not save the layer %s, there was an upload ' 'error: %s' % (layer.name()), traceback.format_exc()) except ConflictingDataError as e: # A datastore of this name already exists raise GeoserverException('GeoServer reported a conflict creating a store with name %s:' % layer.name(), traceback.format_exc()) # Verify the resource was created resources = self.catalog.get_resources(name) if resources: resource = resources[0] assert resource.name == name else: msg = ('could not create layer %s.' % name) raise Exception(msg) if title != name: resource.dirty["title"] = title self.catalog.save(resource) if resource.latlon_bbox is None: box = resource.native_bbox[:4] minx, maxx, miny, maxy = [float(a) for a in box] if -180 <= minx <= 180 and -180 <= maxx <= 180 and \ -90 <= miny <= 90 and -90 <= maxy <= 90: resource.latlon_bbox = resource.native_bbox resource.projection = "EPSG:4326" self.catalog.save(resource) else: msg = ('Could not set projection for layer ' '[%s]. the layer has been created, but its projection should be set manually.') raise Exception(msg % layer.name())
def testVectorFontStylingUpload(self): layer = layers.resolveLayer(PT1) sld, icons = getGsCompatibleSld(layer) #QgsMessageLog.logMessage("sld:" + sld, level=QgsMessageLog.WARNING) sldfile = os.path.join(os.path.dirname(__file__), "resources", "font.sld") with open(sldfile, 'r') as f: sldref = f.read() self.compareSld(sldref, sld)
def publishStyle(self, layer, overwrite = True, name = None): ''' Publishes the style of a given layer style in the specified catalog. If the overwrite parameter is True, it will overwrite a style with that name in case it exists ''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) sld = getGsCompatibleSld(layer) if sld is not None: name = name if name is not None else layer.name() name = name.replace(" ", "_") self.catalog.create_style(name, sld, overwrite) return sld
def publishStyle(self, layer, overwrite=True, name=None): ''' Publishes the style of a given layer style in the specified catalog. If the overwrite parameter is True, it will overwrite a style with that name in case it exists ''' if isinstance(layer, str): layer = layers.resolveLayer(layer) sld, icons = getGsCompatibleSld(layer) if sld is not None: name = name if name is not None else layer.name() name = name.replace(" ", "_") self.uploadIcons(icons) self.catalog.create_style(name, sld.encode('utf-8'), overwrite) return sld
def testDuplicatedLayerNamesInDifferentWorkSpaces(self): """ Test that when there are more than one layer with the same name they can be both added to QGIS """ return self.cat.catalog.create_workspace(WORKSPACEB, "http://testb.com") wsb = self.cat.catalog.get_workspaces(WORKSPACEB)[0] # Need to use prefixed names when retrieving pt1 = self.ws.name + ':' + PT1 pt1b = wsb.name + ':' + PT1 self.cat.publishLayer(PT1, self.ws, name=PT1) self.assertIsNotNone(self.cat.catalog.get_layer(pt1)) self.cat.addLayerToProject(pt1, pt1) layer = layers.resolveLayer(pt1) # Add second layer with the same name self.cat.publishLayer(PT1, wsb, name=PT1) self.assertIsNotNone(self.cat.catalog.get_layer(pt1b)) self.cat.addLayerToProject(pt1b, pt1b) layerb = layers.resolveLayer(pt1b) self.assertNotEqual(layer, layerb) # Check uris self.assertNotEqual(layer.publicSource(), layerb.publicSource()) self.assertNotEqual( QgsProject.instance().mapLayersByName(layer.name()), []) self.assertNotEqual( QgsProject.instance().mapLayersByName(layerb.name()), []) QgsProject.instance().removeMapLayer(layer.id()) QgsProject.instance().removeMapLayer(layerb.id()) self.cat.catalog.delete(self.cat.catalog.get_layer(pt1), recurse=True) self.cat.catalog.delete(self.cat.catalog.get_layer(pt1b), recurse=True)
def testPreuploadVectorHook(self): if not catalog.processingOk: print 'skipping testPreuploadVectorHook, processing not installed' return settings = QSettings() oldHookFile = str(settings.value("/GeoServer/Settings/GeoServer/PreuploadVectorHook", "")) hookFile = os.path.join(os.path.dirname(__file__), "resources", "vector_hook.py") settings.setValue("/GeoServer/Settings/GeoServer/PreuploadVectorHook", hookFile) self.cat.publishLayer(PT1, self.ws, name = HOOK) self.assertIsNotNone(self.cat.catalog.get_layer(HOOK)) self.cat.addLayerToProject(HOOK) layer = layers.resolveLayer(HOOK) self.assertEqual(1, layer.featureCount()) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) settings.setValue("/GeoServer/Settings/GeoServer/PreuploadVectorHook", oldHookFile) self.cat.catalog.delete(self.cat.catalog.get_layer(HOOK), recurse = True)
def publishLayer(self, layer, workspace=None, overwrite=True, name=None, style=None): ''' Publishes a QGIS layer. It creates the corresponding store and the layer itself. If a pre-upload hook is set, its runs it and publishes the resulting layer layer: the layer to publish, whether as a QgsMapLayer object or its name in the QGIS TOC. workspace: the workspace to publish to. USes the default workspace if not passed or None name: the name for the published layer. Uses the QGIS layer name if not passed or None style: the style to use from the ones in the catalog. Will upload the QGIS style if not passed or None ''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) addTrackedLayer(layer, self.catalog.service_url) name = xmlNameFixUp(name) if name is not None \ else xmlNameFixUp(layer.name()) gslayer = self.catalog.get_layer(name) if gslayer is not None and not overwrite: return sld = self.publishStyle(layer, overwrite, name) if style is None else None layer = self.preprocess(layer) self.upload(layer, workspace, overwrite, name) if sld is not None or style is not None: #assign style to created store publishing = self.catalog.get_layer(name) publishing.default_style = style or self.catalog.get_style(name) self.catalog.save(publishing)
def publishLayer (self, layer, workspace=None, overwrite=True, name=None, style=None): ''' Publishes a QGIS layer. It creates the corresponding store and the layer itself. layer: the layer to publish, whether as a QgsMapLayer object or its name in the QGIS TOC. workspace: the workspace to publish to. USes the default workspace if not passed or None name: the name for the published layer. Uses the QGIS layer name if not passed or None style: the style to use from the ones in the catalog. Will upload the QGIS style if not passed or None ''' if isinstance(layer, str): layer = layers.resolveLayer(layer) addTrackedLayer(layer, self.catalog.service_url) name = xmlNameFixUp(name) if name is not None \ else xmlNameFixUp(layer.name()) gslayer = self.catalog.get_layer(name) if gslayer is not None and not overwrite: return sld = self.publishStyle(layer, overwrite, name) if style is None else None self.upload(layer, workspace, overwrite, name) if sld is not None or style is not None: #assign style to created store publishing = self.catalog.get_layer(name) publishing.default_style = style or self.catalog.get_styles(name)[0] self.catalog.save(publishing)
def publishLayer (self, layer, workspace=None, overwrite=True, name=None): ''' Publishes a QGIS layer. It creates the corresponding store and the layer itself. If a pre-upload hook is set, its runs it and publishes the resulting layer layer: the layer to publish, whether as a QgsMapLayer object or its name in the QGIS TOC. workspace: the workspace to publish to. USes the default workspace if not passed or None name: the name for the published layer. Uses the QGIS layer name if not passed or None ''' if isinstance(layer, basestring): layer = layers.resolveLayer(layer) name = xmlNameFixUp(name) if name is not None \ else xmlNameFixUp(layer.name()) gslayer = self.catalog.get_layer(name) if gslayer is not None and not overwrite: return title = name sld = self.publishStyle(layer, overwrite, name) layer = self.preprocess(layer) self.upload(layer, workspace, overwrite, title) if sld is not None: #assign style to created store publishing = self.catalog.get_layer(name) publishing.default_style = self.catalog.get_style(name) self.catalog.save(publishing)
def testPreuploadVectorHook(self): if not catalog.processingOk: print 'skipping testPreuploadVectorHook, processing not installed' return oldHookFile = pluginSetting("PreuploadVectorHook") hookFile = os.path.join(os.path.dirname(__file__), "resources", "vector_hook.py") setPluginSetting("PreuploadVectorHook", hookFile) try: hookFile = pluginSetting("PreuploadVectorHook") try: self.cat.getAlgorithmFromHookFile(hookFile) except: raise Exception("Processing hook cannot be executed") self.cat.publishLayer(PT1, self.ws, name=HOOK) self.assertIsNotNone(self.cat.catalog.get_layer(HOOK)) self.cat.addLayerToProject(HOOK) layer = layers.resolveLayer(HOOK) self.assertEqual(1, layer.featureCount()) QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) finally: setPluginSetting("PreuploadVectorHook", oldHookFile) self.cat.catalog.delete(self.cat.catalog.get_layer(HOOK), recurse=True)
def testVectorFontStylingUpload(self): layer = layers.resolveLayer(PT1) sld, icons = getGsCompatibleSld(layer) self.assertTrue("<WellKnownName>ttf://DejaVu Sans#0x46</WellKnownName>" in sld)
def upload(self, layer, workspace=None, overwrite=True, name=None): '''uploads the specified layer''' if isinstance(layer, str): layer = layers.resolveLayer(layer) name = name or layer.name() title = name name = name.replace(" ", "_") if layer.type() not in (layer.RasterLayer, layer.VectorLayer): raise Exception(layer.name() + ' is not a valid raster or vector layer') provider = layer.dataProvider() try: if layer.type() == layer.RasterLayer: path = self.getDataFromLayer(layer) self.catalog.create_coveragestore(name, path=path, workspace=workspace) elif layer.type() == layer.VectorLayer: path = self.getDataFromLayer(layer) self.catalog.create_featurestore(name, data=path, workspace=workspace, overwrite=overwrite) except UploadError as e: raise Exception( 'Could not save the layer %s, there was an upload ' 'error: %s' % (layer.name()), traceback.format_exc()) except ConflictingDataError as e: # A datastore of this name already exists raise GeoserverException( 'GeoServer reported a conflict creating a store with name %s:' % layer.name(), traceback.format_exc()) # Verify the resource was created resources = self.catalog.get_resources(name) if resources: resource = resources[0] assert resource.name == name else: msg = ('could not create layer %s.' % name) raise Exception(msg) if title != name: resource.dirty["title"] = title self.catalog.save(resource) if resource.latlon_bbox is None: box = resource.native_bbox[:4] minx, maxx, miny, maxy = [float(a) for a in box] if -180 <= minx <= 180 and -180 <= maxx <= 180 and \ -90 <= miny <= 90 and -90 <= maxy <= 90: resource.latlon_bbox = resource.native_bbox resource.projection = "EPSG:4326" self.catalog.save(resource) else: msg = ( 'Could not set projection for layer ' '[%s]. the layer has been created, but its projection should be set manually.' ) raise Exception(msg % layer.name())
def testVectorFontStylingUpload(self): layer = layers.resolveLayer(PT1) sld, icons = getGsCompatibleSld(layer) self.assertTrue( "<WellKnownName>ttf://DejaVu Sans#0x46</WellKnownName>" in sld)