def test_check_layers(self, cap_mock, web_request, dbsession): from c2cgeoportal_commons.models import main server = ogc_server() dbsession.add(server) layer1 = main.LayerWMS(name="layer1", layer="layer1") layer1.ogc_server = server dbsession.add(layer1) layer_missing = main.LayerWMS(name="layer_missing", layer="layer_missing") layer_missing.ogc_server = server dbsession.add(layer_missing) style_missing = main.LayerWMS(name="style_missing", layer="layer1") style_missing.ogc_server = server style_missing.style = "style_missing" dbsession.add(style_missing) dbsession.flush() layers = dbsession.query(main.LayerWMS).filter(main.LayerWMS.ogc_server == server) assert layers.count() == 3 synchronizer = self.synchronizer(web_request, server) synchronizer.check_layers() assert synchronizer.report() == ( "Layer layer_missing does not exists on OGC server\n" "Style style_missing does not exists in Layer layer1\n" "Checked 3 layers, 2 are invalid\n" )
def do_synchronize(self) -> None: self._items_found = 0 self._themes_added = 0 self._groups_added = 0 self._groups_removed = 0 self._layers_added = 0 self._layers_removed = 0 self._default_wms = cast( main.LayerWMS, main.LayerWMS.get_default(self._request.dbsession) or main.LayerWMS() ) self._interfaces = self._request.dbsession.query(main.Interface).all() capabilities = ElementTree.fromstring(self.wms_capabilities()) theme_layers = capabilities.findall("Capability/Layer/Layer") for theme_layer in theme_layers: self.synchronize_layer(theme_layer) if self._clean: self.check_layers() self._logger.info("%s items found", self._items_found) self._logger.info("%s themes added", self._themes_added) self._logger.info("%s groups added", self._groups_added) self._logger.info("%s groups removed", self._groups_removed) self._logger.info("%s layers added", self._layers_added) self._logger.info("%s layers removed", self._layers_removed)
def test_get_layer_wms_defaut_style_not_exists(self, web_request, dbsession): """We should not copy style from default LayerWMS if does not exist in capabilities""" from c2cgeoportal_commons.models import main synchronizer = self.synchronizer(web_request) default_wms = main.LayerWMS() default_wms.style = "not_existing_style" synchronizer._default_wms = default_wms synchronizer._interfaces = [] el = etree.fromstring( """ <Layer> <Name>layer1</Name> <Style> <Name>default</Name> <Title>default</Title> </Style> </Layer> """ ) layer = synchronizer.get_layer_wms(el, None) assert layer.style is None
def test_search_alias(self, dbsession, settings, test_data): from c2cgeoportal_commons.models import main from c2cgeoportal_geoportal.scripts.theme2fts import Import alias_layer = main.LayerWMS(name="alias_layer") alias_layer.ogc_server = test_data["ogc_server"] alias_layer.interfaces = list(test_data["interfaces"].values()) add_parent(dbsession, alias_layer, test_data["groups"]["first_level_group"]) alias_layer.metadatas = [ main.Metadata(name="searchAlias", value="myalias,mykeyword"), main.Metadata(name="searchAlias", value="myotheralias,myotherkeyword"), ] dbsession.add(alias_layer) dbsession.flush() Import(dbsession, settings, options()) for lang in settings["available_locale_names"]: for interface in test_data["interfaces"].values(): if interface.name == "api": continue expected = [ { "label": f"alias_layer_{lang}", "role": None, "interface": interface, "lang": lang, "public": True, "ts": { "fr": "'ali':1 'fr':3 'lai':2 'myali':4 'mykeyword':5 'myotherali':6 'myotherkeyword':7", "en": "'alia':1 'en':3 'layer':2 'myalia':4 'mykeyword':5 'myotheralia':6 'myotherkeyword':7", "de": "'alias':1 'de':3 'lay':2 'myalias':4 'mykeyword':5 'myotheralias':6 'myotherkeyword':7", "it": "'alias':1 'it':3 'layer':2 'myalias':4 'mykeyword':5 'myotheralias':6 'myotherkeyword':7", }, "actions": [{ "action": "add_layer", "data": "alias_layer" }], }, ] for e in expected: self.assert_fts(dbsession, e)
def __init__(self, request: pyramid.request.Request, ogc_server: main.OGCServer) -> None: self._request = request self._ogc_server = ogc_server self._default_wms = main.LayerWMS() self._interfaces = None self._logger = logging.Logger(str(self), logging.INFO) self._log = StringIO() self._log_handler = logging.StreamHandler(self._log) self._logger.addHandler(self._log_handler) self._items_found = 0 self._themes_added = 0 self._groups_added = 0 self._layers_added = 0
def __init__( self, request: pyramid.request.Request, ogc_server: main.OGCServer, force_parents: bool = False, force_ordering: bool = False, clean: bool = False, ) -> None: """ Initialize the Synchronizer. request The current pyramid request object. Used to retrieve the SQLAlchemy Session object, and to construct the capabilities URL. ogc_server The considered OGCServer from witch to import the capabilities. force_parents When set to True, overwrite parents of each node with those from the capabilities. force_ordering When set to True, sort children of each node in order from the capabilities. clean When set to True, remove layers which do not exist in capabilities and remove all empty groups. """ self._request = request self._ogc_server = ogc_server self._force_parents = force_parents self._force_ordering = force_ordering self._clean = clean self._default_wms = main.LayerWMS() self._interfaces = None self._logger = logging.Logger(str(self), logging.INFO) self._log = StringIO() self._log_handler = logging.StreamHandler(self._log) self._logger.addHandler(self._log_handler) self._items_found = 0 self._themes_added = 0 self._groups_added = 0 self._groups_removed = 0 self._layers_added = 0 self._layers_removed = 0
def test_get_layer_wms_defaut(self, web_request, dbsession): """We should copy properties from default LayerWMS""" from c2cgeoportal_commons.models import main synchronizer = self.synchronizer(web_request) default_wms = main.LayerWMS() default_wms.description = "Default description" default_wms.metadatas = [main.Metadata(name="isExpanded", value="True")] default_wms.exclude_properties = "excluded_property" default_wms.interfaces = [main.Interface("interface")] default_wms.dimensions = [ main.Dimension(name="dim", value=None, field="dim", description="description") ] default_wms.style = "default_style" el = etree.fromstring( """ <Layer> <Name>layer1</Name> <Style> <Name>default_style</Name> <Title>default_style</Title> </Style> </Layer> """ ) with patch.object(synchronizer, "_default_wms", default_wms): layer = synchronizer.get_layer_wms(el, None) assert layer.description == "Default description" assert len(layer.metadatas) == 1 assert layer.metadatas[0].name == "isExpanded" assert layer.metadatas[0].value == "True" assert layer.exclude_properties == "excluded_property" assert len(layer.interfaces) == 1 assert layer.interfaces[0].name == "interface" assert len(layer.dimensions) == 1 assert layer.dimensions[0].name == "dim" assert layer.dimensions[0].value is None assert layer.dimensions[0].field == "dim" assert layer.dimensions[0].description == "description" assert layer.style == "default_style"
def test_extract_layer_wms(self, dbsession, transact): from c2cgeoportal_commons.models import main del transact ogc_server = main.OGCServer(name="mapserver", url="http://mapserver:8080") layer_wms = main.LayerWMS(name="layer_wms") layer_wms.ogc_server = ogc_server layer_wms.layer = "testpoint_unprotected" dbsession.add(layer_wms) dbsession.flush() messages = self.extract() assert {m.msgid for m in messages} == { "layer_wms", "testpoint_unprotected", "city", "country", "name", }
def get_layer_wms(self, el: Element, parent: Optional[main.TreeGroup] = None) -> main.LayerWMS: name_el = el.find("Name") assert name_el is not None name = name_el.text layer = cast( Optional[main.LayerWMS], self._request.dbsession.query(main.LayerWMS).filter(main.LayerWMS.name == name).one_or_none(), ) if layer is None: layer = main.LayerWMS() # TreeItem layer.name = name layer.description = self._default_wms.description layer.metadatas = [main.Metadata(name=m.name, value=m.value) for m in self._default_wms.metadatas] # Layer layer.public = False layer.geo_table = None layer.exclude_properties = self._default_wms.exclude_properties layer.interfaces = list(self._default_wms.interfaces) or self._interfaces # DimensionLayer layer.dimensions = [ main.Dimension( name=d.name, value=d.value, field=d.field, description=d.description, ) for d in self._default_wms.dimensions ] # LayerWMS layer.ogc_server = self._ogc_server layer.layer = name layer.style = ( self._default_wms.style if el.find(f"./Style/Name[.='{self._default_wms.style}']") is not None else None ) # layer.time_mode = # layer.time_widget = self._request.dbsession.add(layer) if not isinstance(parent, main.LayerGroup): self._logger.info("Layer %s added as new layer with no parent", name) else: layer.parents_relation.append(main.LayergroupTreeitem(group=parent)) self._logger.info("Layer %s added as new layer in group %s", name, parent.name) self._layers_added += 1 else: self._items_found += 1 if layer.ogc_server is not self._ogc_server: self._logger.info( "Layer %s: another layer already exists with the same name in OGC server %s", name, self._ogc_server.name, ) parents = [parent] if isinstance(parent, main.LayerGroup) else [] if self._force_parents and layer.parents != parents: layer.parents_relation = [main.LayergroupTreeitem(group=parent) for parent in parents] self._logger.info("Layer %s moved to %s", name, parent.name if parent else "root") return layer
def test_data(dbsession, transact): from c2cgeoportal_commons.models import main ogc_server = main.OGCServer(name="ogc_server") dbsession.add(ogc_server) interfaces = { i.name: i for i in [main.Interface(name=name) for name in ["desktop", "mobile", "api"]] } dbsession.add_all(interfaces.values()) role = main.Role(name="role") dbsession.add(role) public_theme = main.Theme(name="public_theme") public_theme.interfaces = list(interfaces.values()) private_theme = main.Theme(name="private_theme") private_theme.public = False private_theme.interfaces = list(interfaces.values()) private_theme.restricted_roles = [role] themes = {t.name: t for t in [public_theme, private_theme]} dbsession.add_all(themes.values()) first_level_group = main.LayerGroup(name="first_level_group") add_parent(dbsession, first_level_group, public_theme) add_parent(dbsession, first_level_group, private_theme) second_level_group = main.LayerGroup(name="second_level_group") add_parent(dbsession, second_level_group, first_level_group) groups = {g.name: g for g in [first_level_group, second_level_group]} dbsession.add_all(groups.values()) public_layer = main.LayerWMS(name="public_layer") public_layer.ogc_server = ogc_server public_layer.interfaces = list(interfaces.values()) add_parent(dbsession, public_layer, first_level_group) private_layer = main.LayerWMS(name="private_layer", public=False) private_layer.ogc_server = ogc_server private_layer.interfaces = list(interfaces.values()) add_parent(dbsession, private_layer, second_level_group) layers = {layer.name: layer for layer in [public_layer, private_layer]} dbsession.add_all(layers.values()) ra = main.RestrictionArea(name="ra") ra.roles = [role] ra.layers = [private_layer] dbsession.add(ra) dbsession.flush() # Flush here to detect integrity errors now. yield { "ogc_server": ogc_server, "interfaces": interfaces, "role": role, "themes": themes, "groups": groups, "layers": layers, "restriction_area": ra, }