Exemplo n.º 1
0
    def test_get_class_enumerations_config(self):
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        enumerations_config = {
            "child1_id": {
                "value": "id",
                "order_by": "name"
            }
        }

        self._create_table("table_d")
        cls = get_class("table_d", enumerations_config=enumerations_config)

        self.assertEqual(enumerations_config, cls.__enumerations_config__)
        association_proxy = getattr(cls,
                                    cls.child1_id.info["association_proxy"])
        self.assertEqual("id", association_proxy.value_attr)
        self.assertEqual("name", association_proxy.order_by)

        # Without order_by.
        enumerations_config = {"child1_id": {"value": "id"}}
        cls = get_class("table_d", enumerations_config=enumerations_config)

        association_proxy = getattr(cls,
                                    cls.child1_id.info["association_proxy"])
        self.assertEqual("id", association_proxy.value_attr)
        self.assertEqual("id", association_proxy.order_by)
    def test_get_class_exclude_properties(self):
        import c2cgeoportal_geoportal.lib.dbreflection
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        self._create_table("table_d")
        get_class("table_d", exclude_properties=["foo", "bar"])

        # the class should now be in the cache
        self.assertTrue(
            ("public", "table_d", ("foo", "bar"), None, (),
             ()) in c2cgeoportal_geoportal.lib.dbreflection._class_cache)
Exemplo n.º 3
0
def get_layer_class(layer, with_last_update_columns=False):
    """
    Get the SQLAlchemy class to edit a GeoMapFish layer

    :param layer:
    :param with_last_update_columns: False to just have a class to access to the table and be able to
           modify the last_update_columns, True to have a correct class to build the UI
           (without the hidden column).
    :return: SQLAlchemy class
    """
    # Exclude the columns used to record the last features update
    exclude = [] if layer.exclude_properties is None else layer.exclude_properties.split(
        ",")
    if with_last_update_columns:
        last_update_date = Layers.get_metadata(layer, "lastUpdateDateColumn")
        if last_update_date is not None:
            exclude.append(last_update_date)
        last_update_user = Layers.get_metadata(layer, "lastUpdateUserColumn")
        if last_update_user is not None:
            exclude.append(last_update_user)
    else:
        exclude = []

    m = Layers.get_metadata(layer, "editingAttributesOrder")
    attributes_order = m.split(",") if m else None
    m = Layers.get_metadata(layer, "readonlyAttributes")
    readonly_attributes = m.split(",") if m else None

    primary_key = Layers.get_metadata(layer, "geotablePrimaryKey")
    cls = get_class(
        str(layer.geo_table.format(os.environ)),
        exclude_properties=exclude,
        primary_key=primary_key,
        attributes_order=attributes_order,
        readonly_attributes=readonly_attributes,
    )

    mapper = class_mapper(cls)
    column_properties = [
        p.key for p in mapper.iterate_properties
        if isinstance(p, ColumnProperty)
    ]
    for attribute_name in attributes_order or []:
        if attribute_name not in column_properties:
            table = mapper.mapped_table
            LOG.warning(
                'Attribute "%s" does not exists in table "%s.%s".\n'
                'Please correct metadata "editingAttributesOrder" in layer "%s" (id=%s).\n'
                "Available attributes are: %s.",
                attribute_name,
                table.schema,
                table.name,
                layer.name,
                layer.id,
                ", ".join(column_properties),
            )

    return cls
Exemplo n.º 4
0
    def test_get_class_attributes_order(self):
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        attributes_order = ["child1_id", "point", "child2_id"]

        self._create_table("table_d")
        cls = get_class("table_d", attributes_order=attributes_order)

        self.assertEqual(attributes_order, cls.__attributes_order__)
Exemplo n.º 5
0
def get_layer_metadatas(layer):
    # exclude the columns used to record the last features update
    exclude = [] if layer.exclude_properties is None else layer.exclude_properties.split(
        ",")

    date_metadata = layer.get_metadatas("lastUpdateDateColumn")
    last_update_date = date_metadata[0] if len(date_metadata) == 1 else None
    if last_update_date is not None:
        exclude.append(last_update_date.value)
    user_metadata = layer.get_metadatas("lastUpdateUserColumn")
    last_update_user = user_metadata[0] if len(user_metadata) == 1 else None
    if last_update_user is not None:
        exclude.append(last_update_user.value)

    cls = get_class(layer.geo_table, exclude_properties=exclude)

    edit_columns = []

    for column_property in class_mapper(cls).iterate_properties:
        if isinstance(column_property, ColumnProperty):

            if len(column_property.columns) != 1:
                raise NotImplementedError  # pragma: no cover

            column = column_property.columns[0]

            # Exclude columns that are primary keys
            if not column.primary_key:
                properties = _convert_column_type(column.type)
                properties["name"] = column.key

                if column.nullable:
                    properties["nillable"] = True
                edit_columns.append(properties)
        else:
            for k, p in cls.__dict__.items():
                if not isinstance(p, _AssociationProxy):
                    continue

                relationship_property = class_mapper(cls) \
                    .get_property(p.target)
                target_cls = relationship_property.argument
                query = models.DBSession.query(
                    getattr(target_cls, p.value_attr))
                properties = {}
                if column.nullable:
                    properties["nillable"] = True

                properties["name"] = k
                properties["restriction"] = "enumeration"
                properties["type"] = "xsd:string"
                properties["enumeration"] = []
                for value in query:
                    properties["enumeration"].append(value[0])

                edit_columns.append(properties)
    return edit_columns
Exemplo n.º 6
0
    def test_get_class_dotted_notation(self):
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        self._create_table("table_b")
        modelclass = get_class("public.table_b")

        assert modelclass.__name__.startswith("Table_b_")
        self.assertEqual(modelclass.__table__.name, "table_b")
        self.assertEqual(modelclass.__table__.schema, "public")
Exemplo n.º 7
0
    def test_get_class_readonly_attributes(self):
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        readonly_attributes = ["child1_id", "point"]

        self._create_table("table_d")
        cls = get_class("table_d", readonly_attributes=readonly_attributes)

        self.assertEqual(True, cls.child1_id.info.get("readonly"))
        self.assertEqual(True, cls.point.info.get("readonly"))
    def test_get_class_attributes_order(self):
        import c2cgeoportal_geoportal.lib.dbreflection
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        attributes_order = ["child1_id", "point", "child2_id"]

        self._create_table("table_d")
        cls = get_class("table_d", attributes_order=attributes_order)

        self.assertEqual(attributes_order, cls.__attributes_order__)

        # the class should now be in the cache
        self.assertTrue(
            ("public", "table_d", (), None, ("child1_id", "point",
                                             "child2_id"),
             ()) in c2cgeoportal_geoportal.lib.dbreflection._class_cache)
Exemplo n.º 9
0
def get_layer_class(layer):
    # exclude the columns used to record the last features update
    exclude = [] if layer.exclude_properties is None else layer.exclude_properties.split(",")
    last_update_date = Layers.get_metadata(layer, "lastUpdateDateColumn")
    if last_update_date is not None:
        exclude.append(last_update_date)
    last_update_user = Layers.get_metadata(layer, "lastUpdateUserColumn")
    if last_update_user is not None:
        exclude.append(last_update_user)

    primary_key = Layers.get_metadata(layer, "geotablePrimaryKey")
    return get_class(
        str(layer.geo_table),
        exclude_properties=exclude,
        primary_key=primary_key
    )
Exemplo n.º 10
0
    def test_get_class_readonly_attributes(self):
        import c2cgeoportal_geoportal.lib.dbreflection
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        readonly_attributes = ["child1_id", "point"]

        self._create_table("table_d")
        cls = get_class("table_d", readonly_attributes=readonly_attributes)

        self.assertEqual(True, cls.child1_id.info.get('readonly'))
        self.assertEqual(True, cls.point.info.get('readonly'))

        # the class should now be in the cache
        self.assertTrue(("public", "table_d", (), None, (), (
            "child1_id",
            "point")) in c2cgeoportal_geoportal.lib.dbreflection._class_cache)
Exemplo n.º 11
0
    def _get_geom_col_info(layer):
        """ Return information about the layer's geometry column, namely
        a ``(name, srid)`` tuple, where ``name`` is the name of the
        geometry column, and ``srid`` its srid.

        This function assumes that the names of geometry attributes
        in the mapped class are the same as those of geometry columns.
        """
        mapped_class = get_class(layer.geo_table)
        for p in class_mapper(mapped_class).iterate_properties:
            if not isinstance(p, ColumnProperty):
                continue  # pragma: no cover
            col = p.columns[0]
            if isinstance(col.type, Geometry):
                return col.name, col.type.srid
        raise HTTPInternalServerError(
            'Failed getting geometry column info for table "{0!s}".'.format(
                layer.geo_table))  # pragma: no cover
Exemplo n.º 12
0
    def metadata(self):
        set_common_headers(self.request, "layers", PRIVATE_CACHE)

        layer = self._get_layer_for_request()
        if not layer.public and self.request.user is None:
            raise HTTPForbidden()

        # exclude the columns used to record the last features update
        exclude = [] if layer.exclude_properties is None else layer.exclude_properties.split(
            ",")
        last_update_date = self._get_metadata(layer, "lastUpdateDateColumn")
        if last_update_date is not None:
            exclude.append(last_update_date)
        last_update_user = self._get_metadata(layer, "lastUpdateUserColumn")
        if last_update_user is not None:
            exclude.append(last_update_user)

        return get_class(layer.geo_table, exclude_properties=exclude)
Exemplo n.º 13
0
 def _import_layer_wms(self, layer, messages):
     server = layer.ogc_server
     url = server.url_wfs or server.url
     if url is None:
         return
     for wms_layer in layer.layer.split(","):
         self._import_layer_attributes(url, wms_layer, layer.item_type,
                                       layer.name, messages)
     if layer.geo_table is not None and layer.geo_table != "":
         exclude = [] if layer.exclude_properties is None else layer.exclude_properties.split(
             ",")
         last_update_date = layer.get_metadatas("lastUpdateDateColumn")
         if len(last_update_date) == 1:
             exclude.append(last_update_date[0].value)
         last_update_user = layer.get_metadatas("lastUpdateUserColumn")
         if len(last_update_user) == 1:
             exclude.append(last_update_user[0].value)
         try:
             cls = get_class(layer.geo_table, exclude_properties=exclude)
             for column_property in class_mapper(cls).iterate_properties:
                 if isinstance(column_property, ColumnProperty) and len(
                         column_property.columns) == 1:
                     column = column_property.columns[0]
                     if not column.primary_key and not isinstance(
                             column.type, Geometry):
                         if column.foreign_keys:
                             name = "type_" if column.name == "type_id" else \
                                 column.name[0:column.name.rindex("_id")]
                         else:
                             name = column_property.key
                         messages.append(
                             Message(None, name, None, [], "", "",
                                     (".".join([
                                         "edit", layer.item_type,
                                         str(layer.id)
                                     ]), layer.name)))
         except NoSuchTableError:
             print(
                 colorize(
                     "ERROR! No such table '{}' for layer '{}'.".format(
                         layer.geo_table, layer.name), RED))
             print(colorize(traceback.format_exc(), RED))
             if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE":
                 raise
Exemplo n.º 14
0
    def test_mixing_get_class_and_queries(self):
        """ This test shows that we can mix the use of DBSession
        and the db reflection API. """
        from c2cgeoportal_geoportal.lib.dbreflection import get_class
        from c2cgeoportal_commons.models import DBSession
        from sqlalchemy import text
        import transaction

        self._create_table("table_c")

        DBSession.execute(text("SELECT id FROM table_c"))

        modelclass = get_class("table_c")
        self.assertEqual(modelclass.__name__, "Table_c")

        # This commits the transaction created by DBSession.execute. This
        # is required here in the test because tearDown does table.drop,
        # which will block forever if the transaction is not committed.
        transaction.commit()
Exemplo n.º 15
0
 def _import_layer_wms(self, layer, messages):
     server = layer.ogc_server
     url = server.url_wfs or server.url
     if url is None:
         return
     for wms_layer in layer.layer.split(","):
         self._import_layer_attributes(url, wms_layer, layer.item_type, layer.name, messages)
     if layer.geo_table is not None and layer.geo_table != "":
         exclude = [] if layer.exclude_properties is None else layer.exclude_properties.split(",")
         last_update_date = layer.get_metadatas("lastUpdateDateColumn")
         if len(last_update_date) == 1:
             exclude.append(last_update_date[0].value)
         last_update_user = layer.get_metadatas("lastUpdateUserColumn")
         if len(last_update_user) == 1:
             exclude.append(last_update_user[0].value)
         try:
             cls = get_class(layer.geo_table, exclude_properties=exclude)
             for column_property in class_mapper(cls).iterate_properties:
                 if isinstance(column_property, ColumnProperty) and len(column_property.columns) == 1:
                     column = column_property.columns[0]
                     if not column.primary_key and not isinstance(column.type, Geometry):
                         if column.foreign_keys:
                             name = "type_" if column.name == "type_id" else \
                                 column.name[0:column.name.rindex("_id")]
                         else:
                             name = column_property.key
                         messages.append(Message(
                             None, name, None, [], "", "",
                             (".".join(["edit", layer.item_type, str(layer.id)]), layer.name)
                         ))
         except NoSuchTableError:
             print(colorize(
                 "ERROR! No such table '{}' for layer '{}'.".format(layer.geo_table, layer.name),
                 RED
             ))
             print(colorize(traceback.format_exc(), RED))
             if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE":
                 raise
Exemplo n.º 16
0
 def _get_protocol_for_layer(self, layer, **kwargs):
     """ Returns a papyrus ``Protocol`` for the ``Layer`` object. """
     cls = get_class(layer.geo_table)
     geom_attr = self._get_geom_col_info(layer)[0]
     return Protocol(models.DBSession, cls, geom_attr, **kwargs)
Exemplo n.º 17
0
    def test_get_class(self):
        from geoalchemy2 import Geometry
        import c2cgeoportal_geoportal.lib.dbreflection
        from c2cgeoportal_geoportal.lib.dbreflection import get_class, _AssociationProxy

        self._create_table("table_a")
        modelclass = get_class("table_a")

        # test the class
        self.assertEqual(modelclass.__name__, "Table_a")
        self.assertEqual(modelclass.__table__.name, "table_a")
        self.assertEqual(modelclass.__table__.schema, "public")

        self.assertTrue(isinstance(modelclass.point.type, Geometry))
        self.assertTrue(isinstance(modelclass.linestring.type, Geometry))
        self.assertTrue(isinstance(modelclass.polygon.type, Geometry))
        self.assertTrue(isinstance(modelclass.multipoint.type, Geometry))
        self.assertTrue(isinstance(modelclass.multilinestring.type, Geometry))
        self.assertTrue(isinstance(modelclass.multipolygon.type, Geometry))

        self.assertTrue(isinstance(modelclass.child1, _AssociationProxy))
        self.assertTrue(modelclass.child1.nullable)
        self.assertEqual(modelclass.child1_id.info.get('association_proxy'),
                         'child1')
        self.assertTrue(isinstance(modelclass.child2, _AssociationProxy))
        self.assertFalse(modelclass.child2.nullable)
        self.assertEqual(modelclass.child2_id.info.get('association_proxy'),
                         'child2')

        # test the Table object
        table = modelclass.__table__
        self.assertTrue("id" in table.c)
        self.assertTrue("child1_id" in table.c)
        self.assertTrue("child2_id" in table.c)
        self.assertTrue("point" in table.c)
        self.assertTrue("linestring" in table.c)
        self.assertTrue("polygon" in table.c)
        self.assertTrue("multipoint" in table.c)
        self.assertTrue("multilinestring" in table.c)
        self.assertTrue("multipolygon" in table.c)
        col_child1_id = table.c["child1_id"]
        self.assertEqual(col_child1_id.name, "child1_id")
        col_child2_id = table.c["child2_id"]
        self.assertEqual(col_child2_id.name, "child2_id")
        col_point = table.c["point"]
        self.assertEqual(col_point.name, "point")
        self.assertEqual(col_point.type.geometry_type, "POINT")
        col_linestring = table.c["linestring"]
        self.assertEqual(col_linestring.name, "linestring")
        self.assertEqual(col_linestring.type.geometry_type, "LINESTRING")
        col_polygon = table.c["polygon"]
        self.assertEqual(col_polygon.name, "polygon")
        self.assertEqual(col_polygon.type.geometry_type, "POLYGON")
        col_multipoint = table.c["multipoint"]
        self.assertEqual(col_multipoint.name, "multipoint")
        self.assertEqual(col_multipoint.type.geometry_type, "MULTIPOINT")
        col_multilinestring = table.c["multilinestring"]
        self.assertEqual(col_multilinestring.name, "multilinestring")
        self.assertEqual(col_multilinestring.type.geometry_type,
                         "MULTILINESTRING")
        col_multipolygon = table.c["multipolygon"]
        self.assertEqual(col_multipolygon.name, "multipolygon")
        self.assertEqual(col_multipolygon.type.geometry_type, "MULTIPOLYGON")

        # the class should now be in the cache
        self.assertTrue(
            ("public", "table_a", (), None, (),
             ()) in c2cgeoportal_geoportal.lib.dbreflection._class_cache)
        _modelclass = get_class("table_a")
        self.assertTrue(_modelclass is modelclass)
Exemplo n.º 18
0
    def test_get_class_exclude_properties(self):
        from c2cgeoportal_geoportal.lib.dbreflection import get_class

        self._create_table("table_d")
        assert get_class("table_d", exclude_properties=["foo", "bar"]) is not None
Exemplo n.º 19
0
    def test_get_class(self):
        from geoalchemy2 import Geometry

        from c2cgeoportal_geoportal.lib.dbreflection import _AssociationProxy, get_class

        init_region({"backend": "dogpile.cache.memory"}, "std")
        init_region({"backend": "dogpile.cache.memory"}, "obj")

        self._create_table("table_a")
        modelclass = get_class("table_a")

        # test the class
        assert modelclass.__name__.startswith("Table_a_")
        self.assertEqual(modelclass.__table__.name, "table_a")
        self.assertEqual(modelclass.__table__.schema, "public")

        self.assertTrue(isinstance(modelclass.point.type, Geometry))
        self.assertTrue(isinstance(modelclass.linestring.type, Geometry))
        self.assertTrue(isinstance(modelclass.polygon.type, Geometry))
        self.assertTrue(isinstance(modelclass.multipoint.type, Geometry))
        self.assertTrue(isinstance(modelclass.multilinestring.type, Geometry))
        self.assertTrue(isinstance(modelclass.multipolygon.type, Geometry))

        self.assertTrue(isinstance(modelclass.child1, _AssociationProxy))
        self.assertTrue(modelclass.child1.nullable)
        self.assertEqual(modelclass.child1_id.info.get("association_proxy"), "child1")
        self.assertTrue(isinstance(modelclass.child2, _AssociationProxy))
        self.assertFalse(modelclass.child2.nullable)
        self.assertEqual(modelclass.child2_id.info.get("association_proxy"), "child2")

        child1_asso_proxy = getattr(modelclass, modelclass.child1_id.info["association_proxy"])
        self.assertEqual("name", child1_asso_proxy.value_attr)
        self.assertEqual("name", child1_asso_proxy.order_by)

        # test the Table object
        table = modelclass.__table__
        self.assertTrue("id" in table.c)
        self.assertTrue("child1_id" in table.c)
        self.assertTrue("child2_id" in table.c)
        self.assertTrue("point" in table.c)
        self.assertTrue("linestring" in table.c)
        self.assertTrue("polygon" in table.c)
        self.assertTrue("multipoint" in table.c)
        self.assertTrue("multilinestring" in table.c)
        self.assertTrue("multipolygon" in table.c)
        col_child1_id = table.c["child1_id"]
        self.assertEqual(col_child1_id.name, "child1_id")
        col_child2_id = table.c["child2_id"]
        self.assertEqual(col_child2_id.name, "child2_id")
        col_point = table.c["point"]
        self.assertEqual(col_point.name, "point")
        self.assertEqual(col_point.type.geometry_type, "POINT")
        col_linestring = table.c["linestring"]
        self.assertEqual(col_linestring.name, "linestring")
        self.assertEqual(col_linestring.type.geometry_type, "LINESTRING")
        col_polygon = table.c["polygon"]
        self.assertEqual(col_polygon.name, "polygon")
        self.assertEqual(col_polygon.type.geometry_type, "POLYGON")
        col_multipoint = table.c["multipoint"]
        self.assertEqual(col_multipoint.name, "multipoint")
        self.assertEqual(col_multipoint.type.geometry_type, "MULTIPOINT")
        col_multilinestring = table.c["multilinestring"]
        self.assertEqual(col_multilinestring.name, "multilinestring")
        self.assertEqual(col_multilinestring.type.geometry_type, "MULTILINESTRING")
        col_multipolygon = table.c["multipolygon"]
        self.assertEqual(col_multipolygon.name, "multipolygon")
        self.assertEqual(col_multipolygon.type.geometry_type, "MULTIPOLYGON")

        assert get_class("table_a") is modelclass