c2cgeoportal-commons 2.8.1.146__py3-none-any.whl → 2.9.0.350__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- c2cgeoportal_commons/__init__.py +1 -1
- c2cgeoportal_commons/alembic/env.py +14 -10
- c2cgeoportal_commons/alembic/main/028477929d13_add_technical_roles.py +2 -2
- c2cgeoportal_commons/alembic/main/04f05bfbb05e_remove_the_old_is_expanded_column.py +3 -1
- c2cgeoportal_commons/alembic/main/116b9b79fc4d_internal_and_external_layer_tables_.py +12 -12
- c2cgeoportal_commons/alembic/main/1418cb05921b_merge_1_6_and_master_branches.py +3 -1
- c2cgeoportal_commons/alembic/main/164ac0819a61_add_image_format_to_wmts_layer.py +2 -2
- c2cgeoportal_commons/alembic/main/166ff2dcc48d_create_database.py +3 -3
- c2cgeoportal_commons/alembic/main/16e43f8c0330_remove_old_metadata_column.py +2 -2
- c2cgeoportal_commons/alembic/main/1d5d4abfebd1_add_restricted_theme.py +2 -2
- c2cgeoportal_commons/alembic/main/1de20166b274_remove_v1_artifacts.py +2 -2
- c2cgeoportal_commons/alembic/main/20137477bd02_update_icons_url.py +2 -2
- c2cgeoportal_commons/alembic/main/21f11066f8ec_trigger_on_role_updates_user_in_static.py +2 -2
- c2cgeoportal_commons/alembic/main/22e6dfb556de_add_description_tree_.py +2 -2
- c2cgeoportal_commons/alembic/main/29f2a32859ec_merge_1_6_and_master_branches.py +3 -1
- c2cgeoportal_commons/alembic/main/2b8ed8c1df94_set_layergroup_treeitem_is_as_a_primary_.py +2 -2
- c2cgeoportal_commons/alembic/main/2e57710fecfe_update_the_ogc_server_for_ogc_api.py +77 -0
- c2cgeoportal_commons/alembic/main/32527659d57b_move_exclude_properties_from_layerv1_to_.py +2 -2
- c2cgeoportal_commons/alembic/main/32b21aa1d0ed_merge_e004f76e951a_and_e004f76e951a_.py +3 -1
- c2cgeoportal_commons/alembic/main/338b57593823_remove_trigger_on_role_name_change.py +2 -2
- c2cgeoportal_commons/alembic/main/415746eb9f6_changes_for_v2.py +2 -2
- c2cgeoportal_commons/alembic/main/44c91d82d419_add_table_log.py +8 -6
- c2cgeoportal_commons/alembic/main/5109242131ce_add_column_time_widget.py +4 -3
- c2cgeoportal_commons/alembic/main/52916d8fde8b_add_sql_fields_to_vector_tiles.py +5 -3
- c2cgeoportal_commons/alembic/main/53ba1a68d5fe_add_theme_to_fulltextsearch.py +2 -2
- c2cgeoportal_commons/alembic/main/54645a535ad6_add_ordering_in_relation.py +2 -2
- c2cgeoportal_commons/alembic/main/56dc90838d90_fix_removing_layerv1.py +2 -2
- c2cgeoportal_commons/alembic/main/596ba21e3833_separate_local_internal.py +2 -2
- c2cgeoportal_commons/alembic/main/678f88c7ad5e_add_vector_tiles_layers_table.py +2 -2
- c2cgeoportal_commons/alembic/main/6a412d9437b1_rename_serverogc_to_ogcserver.py +2 -2
- c2cgeoportal_commons/alembic/main/6d87fdad275a_convert_metadata_to_the_right_case.py +2 -2
- c2cgeoportal_commons/alembic/main/7530011a66a7_trigger_on_role_updates_user_in_static.py +2 -2
- c2cgeoportal_commons/alembic/main/78fd093c8393_add_api_s_intrfaces.py +15 -10
- c2cgeoportal_commons/alembic/main/7d271f4527cd_add_layer_column_in_layerv1_table.py +2 -2
- c2cgeoportal_commons/alembic/main/809650bd04c3_add_dimension_field.py +2 -2
- c2cgeoportal_commons/alembic/main/8117bb9bba16_use_dimension_on_all_the_layers.py +2 -2
- c2cgeoportal_commons/alembic/main/87f8330ed64e_add_missing_delete_cascades.py +2 -2
- c2cgeoportal_commons/alembic/main/9268a1dffac0_add_trigger_to_be_able_to_correctly_.py +2 -2
- c2cgeoportal_commons/alembic/main/94db7e7e5b21_merge_2_2_and_master_branches.py +3 -1
- c2cgeoportal_commons/alembic/main/951ff84bd8ec_be_able_to_delete_a_wms_layer_in_sql.py +2 -2
- c2cgeoportal_commons/alembic/main/a00109812f89_add_field_layer_wms_valid.py +4 -4
- c2cgeoportal_commons/alembic/main/a4558f032d7d_add_support_of_cog_layers.py +74 -0
- c2cgeoportal_commons/alembic/main/a4f1aac9bda_merge_1_6_and_master_branches.py +3 -1
- c2cgeoportal_commons/alembic/main/b60f2a505f42_remame_uimetadata_to_metadata.py +2 -2
- c2cgeoportal_commons/alembic/main/b6b09f414fe8_sync_model_database.py +174 -0
- c2cgeoportal_commons/alembic/main/c75124553bf3_remove_deprecated_columns.py +2 -2
- c2cgeoportal_commons/alembic/main/d48a63b348f1_change_mapserver_url_for_docker.py +2 -2
- c2cgeoportal_commons/alembic/main/d8ef99bc227e_be_able_to_delete_a_linked_functionality.py +2 -2
- c2cgeoportal_commons/alembic/main/daf738d5bae4_merge_2_0_and_master_branches.py +3 -1
- c2cgeoportal_commons/alembic/main/dba87f2647f9_merge_2_2_on_2_3.py +3 -1
- c2cgeoportal_commons/alembic/main/e004f76e951a_add_missing_not_null.py +2 -2
- c2cgeoportal_commons/alembic/main/e7e03dedade3_put_the_default_wms_server_in_the_.py +2 -2
- c2cgeoportal_commons/alembic/main/e85afd327ab3_cascade_deletes_to_tsearch.py +2 -2
- c2cgeoportal_commons/alembic/main/ec82a8906649_add_missing_on_delete_cascade_on_layer_.py +2 -2
- c2cgeoportal_commons/alembic/main/ee25d267bf46_main_interface_desktop.py +2 -2
- c2cgeoportal_commons/alembic/main/eeb345672454_merge_2_4_and_master_branches.py +3 -1
- c2cgeoportal_commons/alembic/static/0c640a58a09a_add_opt_key_column.py +2 -2
- c2cgeoportal_commons/alembic/static/107b81f5b9fe_add_missing_delete_cascades.py +2 -2
- c2cgeoportal_commons/alembic/static/1857owc78a07_add_last_login_and_expiration_date.py +2 -2
- c2cgeoportal_commons/alembic/static/1da396a88908_move_user_table_to_static_schema.py +3 -3
- c2cgeoportal_commons/alembic/static/267b4c1bde2e_add_display_name_in_the_user_for_better_.py +62 -0
- c2cgeoportal_commons/alembic/static/3f89a7d71a5e_alter_column_url_to_remove_limitation.py +2 -2
- c2cgeoportal_commons/alembic/static/44c91d82d419_add_table_log.py +6 -4
- c2cgeoportal_commons/alembic/static/53d671b17b20_add_timezone_on_datetime_fields.py +2 -2
- c2cgeoportal_commons/alembic/static/5472fbc19f39_add_temp_password_column.py +2 -2
- c2cgeoportal_commons/alembic/static/76d72fb3fcb9_add_oauth2_pkce.py +3 -1
- c2cgeoportal_commons/alembic/static/7ef947f30f20_add_oauth2_tables.py +3 -1
- c2cgeoportal_commons/alembic/static/910b4ca53b68_sync_model_database.py +186 -0
- c2cgeoportal_commons/alembic/static/aa41e9613256_wip_add_openid_connect_support.py +64 -0
- c2cgeoportal_commons/alembic/static/ae5e88f35669_add_table_user_role.py +2 -2
- c2cgeoportal_commons/alembic/static/bd029dbfc11a_fill_tech_data_column.py +2 -2
- c2cgeoportal_commons/lib/email_.py +15 -19
- c2cgeoportal_commons/lib/literal.py +3 -3
- c2cgeoportal_commons/lib/url.py +15 -16
- c2cgeoportal_commons/lib/validators.py +1 -1
- c2cgeoportal_commons/models/__init__.py +15 -8
- c2cgeoportal_commons/models/main.py +323 -228
- c2cgeoportal_commons/models/sqlalchemy.py +11 -10
- c2cgeoportal_commons/models/static.py +125 -76
- c2cgeoportal_commons/testing/__init__.py +10 -6
- c2cgeoportal_commons/testing/initializedb.py +7 -6
- {c2cgeoportal_commons-2.8.1.146.dist-info → c2cgeoportal_commons-2.9.0.350.dist-info}/METADATA +4 -9
- c2cgeoportal_commons-2.9.0.350.dist-info/RECORD +89 -0
- {c2cgeoportal_commons-2.8.1.146.dist-info → c2cgeoportal_commons-2.9.0.350.dist-info}/WHEEL +1 -1
- tests/conftest.py +1 -1
- c2cgeoportal_commons-2.8.1.146.dist-info/RECORD +0 -83
- {c2cgeoportal_commons-2.8.1.146.dist-info → c2cgeoportal_commons-2.9.0.350.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2011-
|
|
1
|
+
# Copyright (c) 2011-2025, Camptocamp SA
|
|
2
2
|
# All rights reserved.
|
|
3
3
|
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
|
@@ -30,7 +30,8 @@ import enum
|
|
|
30
30
|
import logging
|
|
31
31
|
import os
|
|
32
32
|
import re
|
|
33
|
-
from
|
|
33
|
+
from datetime import datetime
|
|
34
|
+
from typing import Any, Literal, Optional, cast, get_args
|
|
34
35
|
|
|
35
36
|
import pyramid.request
|
|
36
37
|
import sqlalchemy.orm.base
|
|
@@ -40,24 +41,28 @@ from geoalchemy2.shape import to_shape
|
|
|
40
41
|
from papyrus.geo_interface import GeoInterface
|
|
41
42
|
from sqlalchemy import Column, ForeignKey, Table, UniqueConstraint, event
|
|
42
43
|
from sqlalchemy.ext.declarative import AbstractConcreteBase
|
|
43
|
-
from sqlalchemy.orm import Session, backref, relationship
|
|
44
|
+
from sqlalchemy.orm import Mapped, Session, backref, mapped_column, relationship
|
|
44
45
|
from sqlalchemy.schema import Index
|
|
45
46
|
from sqlalchemy.types import Boolean, DateTime, Enum, Integer, String, Unicode
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
import c2cgeoportal_commons.lib.literal
|
|
48
49
|
from c2cgeoportal_commons.lib.url import get_url2
|
|
49
50
|
from c2cgeoportal_commons.models import Base, _, cache_invalidate_cb
|
|
50
51
|
from c2cgeoportal_commons.models.sqlalchemy import JSONEncodedDict, TsVector
|
|
51
52
|
|
|
52
53
|
try:
|
|
54
|
+
import colander
|
|
53
55
|
from c2cgeoform import default_map_settings
|
|
54
56
|
from c2cgeoform.ext.colander_ext import Geometry as ColanderGeometry
|
|
55
57
|
from c2cgeoform.ext.deform_ext import MapWidget, RelationSelect2Widget
|
|
56
58
|
from colander import drop
|
|
57
59
|
from deform.widget import CheckboxWidget, HiddenWidget, SelectWidget, TextAreaWidget, TextInputWidget
|
|
60
|
+
|
|
61
|
+
colander_null = colander.null
|
|
58
62
|
except ModuleNotFoundError:
|
|
59
|
-
drop = None
|
|
63
|
+
drop = None # pylint: disable=invalid-name
|
|
60
64
|
default_map_settings = {"srid": 3857, "view": {"projection": "EPSG:3857"}}
|
|
65
|
+
colander_null = None # pylint: disable=invalid-name
|
|
61
66
|
|
|
62
67
|
class GenericClass:
|
|
63
68
|
"""Fallback class implementation."""
|
|
@@ -67,11 +72,11 @@ except ModuleNotFoundError:
|
|
|
67
72
|
|
|
68
73
|
CheckboxWidget = GenericClass
|
|
69
74
|
HiddenWidget = GenericClass
|
|
70
|
-
MapWidget = GenericClass
|
|
75
|
+
MapWidget = GenericClass # type: ignore[misc,assignment]
|
|
71
76
|
SelectWidget = GenericClass
|
|
72
77
|
TextAreaWidget = GenericClass
|
|
73
|
-
ColanderGeometry = GenericClass
|
|
74
|
-
RelationSelect2Widget = GenericClass
|
|
78
|
+
ColanderGeometry = GenericClass # type: ignore[misc,assignment]
|
|
79
|
+
RelationSelect2Widget = GenericClass # type: ignore[misc,assignment]
|
|
75
80
|
TextInputWidget = GenericClass
|
|
76
81
|
|
|
77
82
|
|
|
@@ -86,14 +91,16 @@ if os.environ.get("DEVELOPMENT", "0") == "1":
|
|
|
86
91
|
# information
|
|
87
92
|
sqlalchemy.orm.base.state_str = state_str
|
|
88
93
|
|
|
89
|
-
|
|
94
|
+
_LOG = logging.getLogger(__name__)
|
|
90
95
|
|
|
91
96
|
_schema: str = config["schema"] or "main"
|
|
92
97
|
_srid: int = cast(int, config["srid"]) or 3857
|
|
93
98
|
|
|
94
99
|
# Set some default values for the admin interface
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
conf = config.get_config()
|
|
101
|
+
assert conf is not None
|
|
102
|
+
_admin_config: dict[str, Any] = conf.get("admin_interface", {})
|
|
103
|
+
_map_config: dict[str, Any] = {**default_map_settings, **_admin_config.get("map", {})}
|
|
97
104
|
view_srid_match = re.match(r"EPSG:(\d+)", _map_config["view"]["projection"])
|
|
98
105
|
if "map_srid" not in _admin_config and view_srid_match is not None:
|
|
99
106
|
_admin_config["map_srid"] = view_srid_match.group(1)
|
|
@@ -103,22 +110,30 @@ class FullTextSearch(GeoInterface, Base): # type: ignore
|
|
|
103
110
|
"""The tsearch table representation."""
|
|
104
111
|
|
|
105
112
|
__tablename__ = "tsearch"
|
|
106
|
-
__table_args__ = (
|
|
113
|
+
__table_args__ = (
|
|
114
|
+
Index("tsearch_search_index", "ts", "public", "role_id", "interface_id", "lang"),
|
|
115
|
+
Index("tsearch_ts_idx", "ts", postgresql_using="gin"),
|
|
116
|
+
{"schema": _schema},
|
|
117
|
+
)
|
|
107
118
|
|
|
108
|
-
id =
|
|
109
|
-
label =
|
|
110
|
-
layer_name =
|
|
111
|
-
role_id =
|
|
119
|
+
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
120
|
+
label: Mapped[str] = mapped_column(Unicode)
|
|
121
|
+
layer_name: Mapped[str] = mapped_column(Unicode, nullable=True)
|
|
122
|
+
role_id: Mapped[int] = mapped_column(
|
|
123
|
+
Integer, ForeignKey(_schema + ".role.id", ondelete="CASCADE"), nullable=True
|
|
124
|
+
)
|
|
112
125
|
role = relationship("Role")
|
|
113
|
-
interface_id =
|
|
126
|
+
interface_id: Mapped[int] = mapped_column(
|
|
127
|
+
Integer, ForeignKey(_schema + ".interface.id", ondelete="CASCADE"), nullable=True
|
|
128
|
+
)
|
|
114
129
|
interface = relationship("Interface")
|
|
115
|
-
lang =
|
|
116
|
-
public =
|
|
117
|
-
ts =
|
|
118
|
-
the_geom =
|
|
119
|
-
params =
|
|
120
|
-
actions =
|
|
121
|
-
from_theme =
|
|
130
|
+
lang: Mapped[str] = mapped_column(String(2), nullable=True)
|
|
131
|
+
public: Mapped[bool] = mapped_column(Boolean, server_default="true")
|
|
132
|
+
ts = mapped_column(TsVector)
|
|
133
|
+
the_geom = mapped_column(Geometry("GEOMETRY", srid=_srid, spatial_index=False))
|
|
134
|
+
params = mapped_column(JSONEncodedDict, nullable=True)
|
|
135
|
+
actions = mapped_column(JSONEncodedDict, nullable=True)
|
|
136
|
+
from_theme: Mapped[bool] = mapped_column(Boolean, server_default="false")
|
|
122
137
|
|
|
123
138
|
def __str__(self) -> str:
|
|
124
139
|
return f"{self.label}[{self.id}]"
|
|
@@ -133,8 +148,10 @@ class Functionality(Base): # type: ignore
|
|
|
133
148
|
|
|
134
149
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
135
150
|
|
|
136
|
-
id
|
|
137
|
-
|
|
151
|
+
id: Mapped[int] = mapped_column(
|
|
152
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
153
|
+
)
|
|
154
|
+
name: Mapped[str] = mapped_column(
|
|
138
155
|
Unicode,
|
|
139
156
|
nullable=False,
|
|
140
157
|
info={
|
|
@@ -154,7 +171,7 @@ class Functionality(Base): # type: ignore
|
|
|
154
171
|
}
|
|
155
172
|
},
|
|
156
173
|
)
|
|
157
|
-
description =
|
|
174
|
+
description: Mapped[str | None] = mapped_column(
|
|
158
175
|
Unicode,
|
|
159
176
|
info={
|
|
160
177
|
"colanderalchemy": {
|
|
@@ -163,7 +180,7 @@ class Functionality(Base): # type: ignore
|
|
|
163
180
|
}
|
|
164
181
|
},
|
|
165
182
|
)
|
|
166
|
-
value =
|
|
183
|
+
value: Mapped[str] = mapped_column(
|
|
167
184
|
Unicode,
|
|
168
185
|
nullable=False,
|
|
169
186
|
info={
|
|
@@ -224,8 +241,10 @@ class Role(Base): # type: ignore
|
|
|
224
241
|
__colanderalchemy_config__ = {"title": _("Role"), "plural": _("Roles")}
|
|
225
242
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
226
243
|
|
|
227
|
-
id
|
|
228
|
-
|
|
244
|
+
id: Mapped[int] = mapped_column(
|
|
245
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
246
|
+
)
|
|
247
|
+
name: Mapped[str] = mapped_column(
|
|
229
248
|
Unicode,
|
|
230
249
|
unique=True,
|
|
231
250
|
nullable=False,
|
|
@@ -236,7 +255,7 @@ class Role(Base): # type: ignore
|
|
|
236
255
|
}
|
|
237
256
|
},
|
|
238
257
|
)
|
|
239
|
-
description =
|
|
258
|
+
description: Mapped[str | None] = mapped_column(
|
|
240
259
|
Unicode,
|
|
241
260
|
info={
|
|
242
261
|
"colanderalchemy": {
|
|
@@ -245,8 +264,8 @@ class Role(Base): # type: ignore
|
|
|
245
264
|
}
|
|
246
265
|
},
|
|
247
266
|
)
|
|
248
|
-
extent =
|
|
249
|
-
Geometry("POLYGON", srid=_srid),
|
|
267
|
+
extent = mapped_column(
|
|
268
|
+
Geometry("POLYGON", srid=_srid, spatial_index=False),
|
|
250
269
|
info={
|
|
251
270
|
"colanderalchemy": {
|
|
252
271
|
"title": _("Extent"),
|
|
@@ -275,8 +294,8 @@ class Role(Base): # type: ignore
|
|
|
275
294
|
self,
|
|
276
295
|
name: str = "",
|
|
277
296
|
description: str = "",
|
|
278
|
-
functionalities:
|
|
279
|
-
extent: Geometry = None,
|
|
297
|
+
functionalities: list[Functionality] | None = None,
|
|
298
|
+
extent: Geometry | None = None,
|
|
280
299
|
) -> None:
|
|
281
300
|
if functionalities is None:
|
|
282
301
|
functionalities = []
|
|
@@ -289,10 +308,10 @@ class Role(Base): # type: ignore
|
|
|
289
308
|
return f"{self.name}[{self.id}]>"
|
|
290
309
|
|
|
291
310
|
@property
|
|
292
|
-
def bounds(self) ->
|
|
311
|
+
def bounds(self) -> tuple[float, float, float, float] | None: # TODO
|
|
293
312
|
if self.extent is None:
|
|
294
313
|
return None
|
|
295
|
-
return cast(
|
|
314
|
+
return cast(tuple[float, float, float, float], to_shape(self.extent).bounds)
|
|
296
315
|
|
|
297
316
|
|
|
298
317
|
event.listen(Role.functionalities, "set", cache_invalidate_cb)
|
|
@@ -304,15 +323,17 @@ class TreeItem(Base): # type: ignore
|
|
|
304
323
|
"""The treeitem table representation."""
|
|
305
324
|
|
|
306
325
|
__tablename__ = "treeitem"
|
|
307
|
-
__table_args__:
|
|
326
|
+
__table_args__: tuple[Any, ...] | dict[str, Any] = (
|
|
308
327
|
UniqueConstraint("type", "name"),
|
|
309
328
|
{"schema": _schema},
|
|
310
329
|
)
|
|
311
|
-
item_type =
|
|
330
|
+
item_type: Mapped[str] = mapped_column(
|
|
331
|
+
"type", String(10), nullable=False, info={"colanderalchemy": {"exclude": True}}
|
|
332
|
+
)
|
|
312
333
|
__mapper_args__ = {"polymorphic_on": item_type}
|
|
313
334
|
|
|
314
|
-
id =
|
|
315
|
-
name =
|
|
335
|
+
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
336
|
+
name: Mapped[str] = mapped_column(
|
|
316
337
|
Unicode,
|
|
317
338
|
nullable=False,
|
|
318
339
|
info={
|
|
@@ -327,7 +348,7 @@ class TreeItem(Base): # type: ignore
|
|
|
327
348
|
}
|
|
328
349
|
},
|
|
329
350
|
)
|
|
330
|
-
description =
|
|
351
|
+
description: Mapped[str | None] = mapped_column(
|
|
331
352
|
Unicode,
|
|
332
353
|
info={
|
|
333
354
|
"colanderalchemy": {
|
|
@@ -339,7 +360,7 @@ class TreeItem(Base): # type: ignore
|
|
|
339
360
|
|
|
340
361
|
@property
|
|
341
362
|
# Better: def parents(self) -> List[TreeGroup]:
|
|
342
|
-
def parents(self) ->
|
|
363
|
+
def parents(self) -> list["TreeItem"]:
|
|
343
364
|
return [c.treegroup for c in self.parents_relation]
|
|
344
365
|
|
|
345
366
|
def is_in_interface(self, name: str) -> bool:
|
|
@@ -352,7 +373,7 @@ class TreeItem(Base): # type: ignore
|
|
|
352
373
|
|
|
353
374
|
return False
|
|
354
375
|
|
|
355
|
-
def get_metadata(self, name: str) ->
|
|
376
|
+
def get_metadata(self, name: str) -> list["Metadata"]:
|
|
356
377
|
return [metadata for metadata in self.metadatas if metadata.name == name]
|
|
357
378
|
|
|
358
379
|
def __init__(self, name: str = "") -> None:
|
|
@@ -375,11 +396,13 @@ class LayergroupTreeitem(Base): # type: ignore
|
|
|
375
396
|
__table_args__ = {"schema": _schema}
|
|
376
397
|
|
|
377
398
|
# required by formalchemy
|
|
378
|
-
id
|
|
379
|
-
|
|
380
|
-
|
|
399
|
+
id: Mapped[int] = mapped_column(
|
|
400
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
401
|
+
)
|
|
402
|
+
description: Mapped[str | None] = mapped_column(Unicode, info={"colanderalchemy": {"exclude": True}})
|
|
403
|
+
treegroup_id: Mapped[int] = mapped_column(
|
|
381
404
|
Integer,
|
|
382
|
-
ForeignKey(_schema + ".treegroup.id"),
|
|
405
|
+
ForeignKey(_schema + ".treegroup.id", name="treegroup_id_fkey"),
|
|
383
406
|
nullable=False,
|
|
384
407
|
info={"colanderalchemy": {"exclude": True}},
|
|
385
408
|
)
|
|
@@ -394,9 +417,9 @@ class LayergroupTreeitem(Base): # type: ignore
|
|
|
394
417
|
primaryjoin="LayergroupTreeitem.treegroup_id==TreeGroup.id",
|
|
395
418
|
info={"colanderalchemy": {"exclude": True}, "c2cgeoform": {"duplicate": False}},
|
|
396
419
|
)
|
|
397
|
-
treeitem_id =
|
|
420
|
+
treeitem_id: Mapped[int] = mapped_column(
|
|
398
421
|
Integer,
|
|
399
|
-
ForeignKey(_schema + ".treeitem.id"),
|
|
422
|
+
ForeignKey(_schema + ".treeitem.id", ondelete="CASCADE"),
|
|
400
423
|
nullable=False,
|
|
401
424
|
info={"colanderalchemy": {"widget": HiddenWidget()}},
|
|
402
425
|
)
|
|
@@ -413,10 +436,10 @@ class LayergroupTreeitem(Base): # type: ignore
|
|
|
413
436
|
primaryjoin="LayergroupTreeitem.treeitem_id==TreeItem.id",
|
|
414
437
|
info={"colanderalchemy": {"exclude": True}, "c2cgeoform": {"duplicate": False}},
|
|
415
438
|
)
|
|
416
|
-
ordering =
|
|
439
|
+
ordering: Mapped[int] = mapped_column(Integer, info={"colanderalchemy": {"widget": HiddenWidget()}})
|
|
417
440
|
|
|
418
441
|
def __init__(
|
|
419
|
-
self, group: Optional["TreeGroup"] = None, item:
|
|
442
|
+
self, group: Optional["TreeGroup"] = None, item: TreeItem | None = None, ordering: int = 0
|
|
420
443
|
) -> None:
|
|
421
444
|
self.treegroup = group
|
|
422
445
|
self.treeitem = item
|
|
@@ -436,14 +459,18 @@ class TreeGroup(TreeItem):
|
|
|
436
459
|
|
|
437
460
|
__tablename__ = "treegroup"
|
|
438
461
|
__table_args__ = {"schema": _schema}
|
|
439
|
-
__mapper_args__ = {"polymorphic_identity": "treegroup"} # needed for _identity_class
|
|
462
|
+
__mapper_args__ = {"polymorphic_identity": "treegroup"} # type: ignore[dict-item] # needed for _identity_class
|
|
440
463
|
|
|
441
|
-
id =
|
|
464
|
+
id: Mapped[int] = mapped_column(
|
|
465
|
+
Integer,
|
|
466
|
+
ForeignKey(_schema + ".treeitem.id", ondelete="CASCADE", name="treegroup_id_fkey"),
|
|
467
|
+
primary_key=True,
|
|
468
|
+
)
|
|
442
469
|
|
|
443
|
-
def _get_children(self) ->
|
|
470
|
+
def _get_children(self) -> list[TreeItem]:
|
|
444
471
|
return [c.treeitem for c in self.children_relation]
|
|
445
472
|
|
|
446
|
-
def _set_children(self, children:
|
|
473
|
+
def _set_children(self, children: list[TreeItem], order: bool = False) -> None:
|
|
447
474
|
"""
|
|
448
475
|
Set the current TreeGroup children TreeItem instances.
|
|
449
476
|
|
|
@@ -489,7 +516,7 @@ class LayerGroup(TreeGroup):
|
|
|
489
516
|
__colanderalchemy_config__ = {
|
|
490
517
|
"title": _("Layers group"),
|
|
491
518
|
"plural": _("Layers groups"),
|
|
492
|
-
"description": Literal(
|
|
519
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
493
520
|
_(
|
|
494
521
|
"""
|
|
495
522
|
<div class="help-block">
|
|
@@ -502,12 +529,12 @@ class LayerGroup(TreeGroup):
|
|
|
502
529
|
)
|
|
503
530
|
),
|
|
504
531
|
}
|
|
505
|
-
__mapper_args__ = {"polymorphic_identity": "group"}
|
|
532
|
+
__mapper_args__ = {"polymorphic_identity": "group"} # type: ignore[dict-item]
|
|
506
533
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
507
534
|
|
|
508
|
-
id =
|
|
535
|
+
id: Mapped[int] = mapped_column(
|
|
509
536
|
Integer,
|
|
510
|
-
ForeignKey(_schema + ".treegroup.id"),
|
|
537
|
+
ForeignKey(_schema + ".treegroup.id", ondelete="CASCADE"),
|
|
511
538
|
primary_key=True,
|
|
512
539
|
info={"colanderalchemy": {"missing": drop, "widget": HiddenWidget()}},
|
|
513
540
|
)
|
|
@@ -532,19 +559,19 @@ class Theme(TreeGroup):
|
|
|
532
559
|
__tablename__ = "theme"
|
|
533
560
|
__table_args__ = {"schema": _schema}
|
|
534
561
|
__colanderalchemy_config__ = {"title": _("Theme"), "plural": _("Themes")}
|
|
535
|
-
__mapper_args__ = {"polymorphic_identity": "theme"}
|
|
562
|
+
__mapper_args__ = {"polymorphic_identity": "theme"} # type: ignore[dict-item]
|
|
536
563
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
537
564
|
|
|
538
|
-
id =
|
|
565
|
+
id: Mapped[int] = mapped_column(
|
|
539
566
|
Integer,
|
|
540
|
-
ForeignKey(_schema + ".treegroup.id"),
|
|
567
|
+
ForeignKey(_schema + ".treegroup.id", ondelete="CASCADE"),
|
|
541
568
|
primary_key=True,
|
|
542
569
|
info={"colanderalchemy": {"missing": drop, "widget": HiddenWidget()}},
|
|
543
570
|
)
|
|
544
|
-
ordering =
|
|
571
|
+
ordering: Mapped[int] = mapped_column(
|
|
545
572
|
Integer, nullable=False, info={"colanderalchemy": {"title": _("Order"), "widget": HiddenWidget()}}
|
|
546
573
|
)
|
|
547
|
-
public =
|
|
574
|
+
public: Mapped[bool] = mapped_column(
|
|
548
575
|
Boolean,
|
|
549
576
|
default=True,
|
|
550
577
|
nullable=False,
|
|
@@ -555,12 +582,14 @@ class Theme(TreeGroup):
|
|
|
555
582
|
}
|
|
556
583
|
},
|
|
557
584
|
)
|
|
558
|
-
icon =
|
|
585
|
+
icon: Mapped[str] = mapped_column(
|
|
559
586
|
Unicode,
|
|
587
|
+
nullable=True,
|
|
560
588
|
info={
|
|
561
589
|
"colanderalchemy": {
|
|
562
590
|
"title": _("Icon"),
|
|
563
591
|
"description": _("The icon URL."),
|
|
592
|
+
"missing": "",
|
|
564
593
|
}
|
|
565
594
|
},
|
|
566
595
|
)
|
|
@@ -609,15 +638,15 @@ class Layer(TreeItem):
|
|
|
609
638
|
|
|
610
639
|
__tablename__ = "layer"
|
|
611
640
|
__table_args__ = {"schema": _schema}
|
|
612
|
-
__mapper_args__ = {"polymorphic_identity": "layer"} # needed for _identity_class
|
|
641
|
+
__mapper_args__ = {"polymorphic_identity": "layer"} # type: ignore[dict-item] # needed for _identity_class
|
|
613
642
|
|
|
614
|
-
id =
|
|
643
|
+
id: Mapped[int] = mapped_column(
|
|
615
644
|
Integer,
|
|
616
|
-
ForeignKey(_schema + ".treeitem.id"),
|
|
645
|
+
ForeignKey(_schema + ".treeitem.id", ondelete="CASCADE"),
|
|
617
646
|
primary_key=True,
|
|
618
647
|
info={"colanderalchemy": {"widget": HiddenWidget()}},
|
|
619
648
|
)
|
|
620
|
-
public =
|
|
649
|
+
public: Mapped[bool] = mapped_column(
|
|
621
650
|
Boolean,
|
|
622
651
|
default=True,
|
|
623
652
|
info={
|
|
@@ -627,7 +656,7 @@ class Layer(TreeItem):
|
|
|
627
656
|
}
|
|
628
657
|
},
|
|
629
658
|
)
|
|
630
|
-
geo_table =
|
|
659
|
+
geo_table: Mapped[str | None] = mapped_column(
|
|
631
660
|
Unicode,
|
|
632
661
|
info={
|
|
633
662
|
"colanderalchemy": {
|
|
@@ -636,18 +665,22 @@ class Layer(TreeItem):
|
|
|
636
665
|
}
|
|
637
666
|
},
|
|
638
667
|
)
|
|
639
|
-
exclude_properties =
|
|
668
|
+
exclude_properties: Mapped[str] = mapped_column(
|
|
640
669
|
Unicode,
|
|
670
|
+
nullable=True,
|
|
641
671
|
info={
|
|
642
672
|
"colanderalchemy": {
|
|
643
673
|
"title": _("Exclude properties"),
|
|
644
|
-
"description":
|
|
645
|
-
|
|
674
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
675
|
+
_(
|
|
676
|
+
"""
|
|
646
677
|
The list of attributes (database columns) that should not appear in
|
|
647
678
|
the editing form so that they cannot be modified by the end user.
|
|
648
|
-
For enumerable attributes (foreign key), the column name should end with
|
|
679
|
+
For enumerable attributes (foreign key), the column name should end with <code>_id</code>.
|
|
649
680
|
"""
|
|
681
|
+
)
|
|
650
682
|
),
|
|
683
|
+
"missing": "",
|
|
651
684
|
}
|
|
652
685
|
},
|
|
653
686
|
)
|
|
@@ -660,19 +693,27 @@ class Layer(TreeItem):
|
|
|
660
693
|
class DimensionLayer(Layer):
|
|
661
694
|
"""The intermediate class for the leyser with dimension."""
|
|
662
695
|
|
|
663
|
-
__mapper_args__ = {"polymorphic_identity": "dimensionlayer"} # needed for _identity_class
|
|
696
|
+
__mapper_args__ = {"polymorphic_identity": "dimensionlayer"} # type: ignore[dict-item] # needed for _identity_class
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
OGCServerType = Literal["mapserver", "qgisserver", "geoserver", "arcgis", "other"]
|
|
700
|
+
OGCSERVER_TYPE_MAPSERVER: OGCServerType = "mapserver"
|
|
701
|
+
OGCSERVER_TYPE_QGISSERVER: OGCServerType = "qgisserver"
|
|
702
|
+
OGCSERVER_TYPE_GEOSERVER: OGCServerType = "geoserver"
|
|
703
|
+
OGCSERVER_TYPE_ARCGIS: OGCServerType = "arcgis"
|
|
704
|
+
OGCSERVER_TYPE_OTHER: OGCServerType = "other"
|
|
705
|
+
|
|
664
706
|
|
|
707
|
+
OGCServerAuth = Literal["No auth", "Standard auth", "Geoserver auth", "Proxy"]
|
|
708
|
+
OGCSERVER_AUTH_NOAUTH: OGCServerAuth = "No auth"
|
|
709
|
+
OGCSERVER_AUTH_STANDARD: OGCServerAuth = "Standard auth"
|
|
710
|
+
OGCSERVER_AUTH_GEOSERVER: OGCServerAuth = "Geoserver auth"
|
|
711
|
+
OGCSERVER_AUTH_PROXY: OGCServerAuth = "Proxy"
|
|
665
712
|
|
|
666
|
-
OGCSERVER_TYPE_MAPSERVER = "mapserver"
|
|
667
|
-
OGCSERVER_TYPE_QGISSERVER = "qgisserver"
|
|
668
|
-
OGCSERVER_TYPE_GEOSERVER = "geoserver"
|
|
669
|
-
OGCSERVER_TYPE_ARCGIS = "arcgis"
|
|
670
|
-
OGCSERVER_TYPE_OTHER = "other"
|
|
671
713
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
OGCSERVER_AUTH_PROXY = "Proxy"
|
|
714
|
+
ImageType = Literal["image/jpeg", "image/png", "image/webp"]
|
|
715
|
+
TimeMode = Literal["disabled", "value", "range"]
|
|
716
|
+
TimeWidget = Literal["slider", "datepicker"]
|
|
676
717
|
|
|
677
718
|
|
|
678
719
|
class OGCServer(Base): # type: ignore
|
|
@@ -683,7 +724,7 @@ class OGCServer(Base): # type: ignore
|
|
|
683
724
|
__colanderalchemy_config__ = {
|
|
684
725
|
"title": _("OGC Server"),
|
|
685
726
|
"plural": _("OGC Servers"),
|
|
686
|
-
"description": Literal(
|
|
727
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
687
728
|
_(
|
|
688
729
|
"""
|
|
689
730
|
<div class="help-block">
|
|
@@ -698,55 +739,58 @@ class OGCServer(Base): # type: ignore
|
|
|
698
739
|
),
|
|
699
740
|
}
|
|
700
741
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
701
|
-
id
|
|
702
|
-
|
|
742
|
+
id: Mapped[int] = mapped_column(
|
|
743
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
744
|
+
)
|
|
745
|
+
name: Mapped[str] = mapped_column(
|
|
703
746
|
Unicode,
|
|
704
747
|
nullable=False,
|
|
705
748
|
unique=True,
|
|
706
749
|
info={
|
|
707
750
|
"colanderalchemy": {
|
|
708
751
|
"title": _("Name"),
|
|
709
|
-
"description":
|
|
752
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
753
|
+
_(
|
|
754
|
+
"The name of the OGC Server should contain only unaccentuated letters, numbers and _. "
|
|
755
|
+
"When you rename it, do not forget to update the <code>ogcServer</code> metadata on the "
|
|
756
|
+
"WMTS and COG layers."
|
|
757
|
+
)
|
|
758
|
+
),
|
|
710
759
|
}
|
|
711
760
|
},
|
|
712
761
|
)
|
|
713
|
-
description =
|
|
762
|
+
description: Mapped[str | None] = mapped_column(
|
|
714
763
|
Unicode,
|
|
715
764
|
info={
|
|
716
765
|
"colanderalchemy": {
|
|
717
766
|
"title": _("Description"),
|
|
718
|
-
"description": _("
|
|
767
|
+
"description": _("An optional description."),
|
|
719
768
|
}
|
|
720
769
|
},
|
|
721
770
|
)
|
|
722
|
-
url =
|
|
771
|
+
url: Mapped[str] = mapped_column(
|
|
723
772
|
Unicode,
|
|
724
773
|
nullable=False,
|
|
725
774
|
info={
|
|
726
775
|
"colanderalchemy": {
|
|
727
776
|
"title": _("Basic URL"),
|
|
728
|
-
"description": _("The server URL"),
|
|
777
|
+
"description": _("The server URL."),
|
|
729
778
|
}
|
|
730
779
|
},
|
|
731
780
|
)
|
|
732
|
-
url_wfs =
|
|
781
|
+
url_wfs: Mapped[str | None] = mapped_column(
|
|
733
782
|
Unicode,
|
|
734
783
|
info={
|
|
735
784
|
"colanderalchemy": {
|
|
736
785
|
"title": _("WFS URL"),
|
|
737
|
-
"description":
|
|
786
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
787
|
+
_("The WFS server URL. If empty, the <code>Basic URL</code> is used.")
|
|
788
|
+
),
|
|
738
789
|
}
|
|
739
790
|
},
|
|
740
791
|
)
|
|
741
|
-
type =
|
|
742
|
-
Enum(
|
|
743
|
-
OGCSERVER_TYPE_MAPSERVER,
|
|
744
|
-
OGCSERVER_TYPE_QGISSERVER,
|
|
745
|
-
OGCSERVER_TYPE_GEOSERVER,
|
|
746
|
-
OGCSERVER_TYPE_ARCGIS,
|
|
747
|
-
OGCSERVER_TYPE_OTHER,
|
|
748
|
-
native_enum=False,
|
|
749
|
-
),
|
|
792
|
+
type: Mapped[OGCServerType] = mapped_column(
|
|
793
|
+
Enum(*get_args(OGCServerType), native_enum=False),
|
|
750
794
|
nullable=False,
|
|
751
795
|
info={
|
|
752
796
|
"colanderalchemy": {
|
|
@@ -754,56 +798,39 @@ class OGCServer(Base): # type: ignore
|
|
|
754
798
|
"description": _(
|
|
755
799
|
"The server type which is used to know which custom attribute will be used."
|
|
756
800
|
),
|
|
757
|
-
"widget": SelectWidget(
|
|
758
|
-
values=(
|
|
759
|
-
(OGCSERVER_TYPE_MAPSERVER, OGCSERVER_TYPE_MAPSERVER),
|
|
760
|
-
(OGCSERVER_TYPE_QGISSERVER, OGCSERVER_TYPE_QGISSERVER),
|
|
761
|
-
(OGCSERVER_TYPE_GEOSERVER, OGCSERVER_TYPE_GEOSERVER),
|
|
762
|
-
(OGCSERVER_TYPE_ARCGIS, OGCSERVER_TYPE_ARCGIS),
|
|
763
|
-
(OGCSERVER_TYPE_OTHER, OGCSERVER_TYPE_OTHER),
|
|
764
|
-
)
|
|
765
|
-
),
|
|
801
|
+
"widget": SelectWidget(values=list((e, e) for e in get_args(OGCServerType))),
|
|
766
802
|
}
|
|
767
803
|
},
|
|
768
804
|
)
|
|
769
|
-
image_type =
|
|
770
|
-
Enum(
|
|
805
|
+
image_type: Mapped[ImageType] = mapped_column(
|
|
806
|
+
Enum(*get_args(ImageType), native_enum=False),
|
|
771
807
|
nullable=False,
|
|
772
808
|
info={
|
|
773
809
|
"colanderalchemy": {
|
|
774
810
|
"title": _("Image type"),
|
|
775
|
-
"description":
|
|
776
|
-
|
|
811
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
812
|
+
_(
|
|
813
|
+
"The MIME type of the images (e.g.: <code>image/png</code>, <code>image/webp</code> is experimental)."
|
|
814
|
+
)
|
|
815
|
+
),
|
|
816
|
+
"widget": SelectWidget(values=list((e, e) for e in get_args(ImageType))),
|
|
777
817
|
"column": 2,
|
|
778
818
|
}
|
|
779
819
|
},
|
|
780
820
|
)
|
|
781
|
-
auth =
|
|
782
|
-
Enum(
|
|
783
|
-
OGCSERVER_AUTH_NOAUTH,
|
|
784
|
-
OGCSERVER_AUTH_STANDARD,
|
|
785
|
-
OGCSERVER_AUTH_GEOSERVER,
|
|
786
|
-
OGCSERVER_AUTH_PROXY,
|
|
787
|
-
native_enum=False,
|
|
788
|
-
),
|
|
821
|
+
auth: Mapped[OGCServerAuth] = mapped_column(
|
|
822
|
+
Enum(*get_args(OGCServerAuth), native_enum=False),
|
|
789
823
|
nullable=False,
|
|
790
824
|
info={
|
|
791
825
|
"colanderalchemy": {
|
|
792
826
|
"title": _("Authentication type"),
|
|
793
827
|
"description": "The kind of authentication to use.",
|
|
794
|
-
"widget": SelectWidget(
|
|
795
|
-
values=(
|
|
796
|
-
(OGCSERVER_AUTH_NOAUTH, OGCSERVER_AUTH_NOAUTH),
|
|
797
|
-
(OGCSERVER_AUTH_STANDARD, OGCSERVER_AUTH_STANDARD),
|
|
798
|
-
(OGCSERVER_AUTH_GEOSERVER, OGCSERVER_AUTH_GEOSERVER),
|
|
799
|
-
(OGCSERVER_AUTH_PROXY, OGCSERVER_AUTH_PROXY),
|
|
800
|
-
)
|
|
801
|
-
),
|
|
828
|
+
"widget": SelectWidget(values=list((e, e) for e in get_args(OGCServerAuth))),
|
|
802
829
|
"column": 2,
|
|
803
830
|
}
|
|
804
831
|
},
|
|
805
832
|
)
|
|
806
|
-
wfs_support =
|
|
833
|
+
wfs_support: Mapped[bool] = mapped_column(
|
|
807
834
|
Boolean,
|
|
808
835
|
info={
|
|
809
836
|
"colanderalchemy": {
|
|
@@ -813,7 +840,7 @@ class OGCServer(Base): # type: ignore
|
|
|
813
840
|
}
|
|
814
841
|
},
|
|
815
842
|
)
|
|
816
|
-
is_single_tile =
|
|
843
|
+
is_single_tile: Mapped[bool] = mapped_column(
|
|
817
844
|
Boolean,
|
|
818
845
|
info={
|
|
819
846
|
"colanderalchemy": {
|
|
@@ -827,12 +854,12 @@ class OGCServer(Base): # type: ignore
|
|
|
827
854
|
def __init__(
|
|
828
855
|
self,
|
|
829
856
|
name: str = "",
|
|
830
|
-
description:
|
|
857
|
+
description: str | None = None,
|
|
831
858
|
url: str = "https://wms.example.com",
|
|
832
|
-
url_wfs:
|
|
833
|
-
type_:
|
|
834
|
-
image_type:
|
|
835
|
-
auth:
|
|
859
|
+
url_wfs: str | None = None,
|
|
860
|
+
type_: OGCServerType = OGCSERVER_TYPE_MAPSERVER,
|
|
861
|
+
image_type: ImageType = "image/png",
|
|
862
|
+
auth: OGCServerAuth = OGCSERVER_AUTH_STANDARD,
|
|
836
863
|
wfs_support: bool = True,
|
|
837
864
|
is_single_tile: bool = False,
|
|
838
865
|
) -> None:
|
|
@@ -850,14 +877,14 @@ class OGCServer(Base): # type: ignore
|
|
|
850
877
|
return self.name or ""
|
|
851
878
|
|
|
852
879
|
def url_description(self, request: pyramid.request.Request) -> str:
|
|
853
|
-
errors:
|
|
880
|
+
errors: set[str] = set()
|
|
854
881
|
url = get_url2(self.name, self.url, request, errors)
|
|
855
882
|
return url.url() if url else "\n".join(errors)
|
|
856
883
|
|
|
857
|
-
def url_wfs_description(self, request: pyramid.request.Request) ->
|
|
884
|
+
def url_wfs_description(self, request: pyramid.request.Request) -> str | None:
|
|
858
885
|
if not self.url_wfs:
|
|
859
886
|
return self.url_description(request)
|
|
860
|
-
errors:
|
|
887
|
+
errors: set[str] = set()
|
|
861
888
|
url = get_url2(self.name, self.url_wfs, request, errors)
|
|
862
889
|
return url.url() if url else "\n".join(errors)
|
|
863
890
|
|
|
@@ -870,7 +897,7 @@ class LayerWMS(DimensionLayer):
|
|
|
870
897
|
__colanderalchemy_config__ = {
|
|
871
898
|
"title": _("WMS Layer"),
|
|
872
899
|
"plural": _("WMS Layers"),
|
|
873
|
-
"description": Literal(
|
|
900
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
874
901
|
_(
|
|
875
902
|
"""
|
|
876
903
|
<div class="help-block">
|
|
@@ -886,15 +913,15 @@ class LayerWMS(DimensionLayer):
|
|
|
886
913
|
|
|
887
914
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
888
915
|
|
|
889
|
-
__mapper_args__ = {"polymorphic_identity": "l_wms"}
|
|
916
|
+
__mapper_args__ = {"polymorphic_identity": "l_wms"} # type: ignore[dict-item]
|
|
890
917
|
|
|
891
|
-
id =
|
|
918
|
+
id: Mapped[int] = mapped_column(
|
|
892
919
|
Integer,
|
|
893
920
|
ForeignKey(_schema + ".layer.id", ondelete="CASCADE"),
|
|
894
921
|
primary_key=True,
|
|
895
922
|
info={"colanderalchemy": {"missing": None, "widget": HiddenWidget()}},
|
|
896
923
|
)
|
|
897
|
-
ogc_server_id =
|
|
924
|
+
ogc_server_id: Mapped[int] = mapped_column(
|
|
898
925
|
Integer,
|
|
899
926
|
ForeignKey(_schema + ".ogc_server.id"),
|
|
900
927
|
nullable=False,
|
|
@@ -908,7 +935,7 @@ class LayerWMS(DimensionLayer):
|
|
|
908
935
|
}
|
|
909
936
|
},
|
|
910
937
|
)
|
|
911
|
-
layer =
|
|
938
|
+
layer: Mapped[str] = mapped_column(
|
|
912
939
|
Unicode,
|
|
913
940
|
nullable=False,
|
|
914
941
|
info={
|
|
@@ -926,7 +953,7 @@ class LayerWMS(DimensionLayer):
|
|
|
926
953
|
}
|
|
927
954
|
},
|
|
928
955
|
)
|
|
929
|
-
style =
|
|
956
|
+
style: Mapped[str | None] = mapped_column(
|
|
930
957
|
Unicode,
|
|
931
958
|
info={
|
|
932
959
|
"colanderalchemy": {
|
|
@@ -936,30 +963,34 @@ class LayerWMS(DimensionLayer):
|
|
|
936
963
|
}
|
|
937
964
|
},
|
|
938
965
|
)
|
|
939
|
-
valid =
|
|
966
|
+
valid: Mapped[bool] = mapped_column(
|
|
940
967
|
Boolean,
|
|
968
|
+
nullable=True,
|
|
941
969
|
info={
|
|
942
970
|
"colanderalchemy": {
|
|
943
971
|
"title": _("Valid"),
|
|
944
972
|
"description": _("The status reported by latest synchronization (readonly)."),
|
|
945
973
|
"column": 2,
|
|
946
974
|
"widget": CheckboxWidget(readonly=True),
|
|
975
|
+
"missing": colander_null,
|
|
947
976
|
}
|
|
948
977
|
},
|
|
949
978
|
)
|
|
950
|
-
invalid_reason =
|
|
979
|
+
invalid_reason: Mapped[str] = mapped_column(
|
|
951
980
|
Unicode,
|
|
981
|
+
nullable=True,
|
|
952
982
|
info={
|
|
953
983
|
"colanderalchemy": {
|
|
954
984
|
"title": _("Reason why I am not valid"),
|
|
955
985
|
"description": _("The reason for status reported by latest synchronization (readonly)."),
|
|
956
986
|
"column": 2,
|
|
957
987
|
"widget": TextInputWidget(readonly=True),
|
|
988
|
+
"missing": "",
|
|
958
989
|
}
|
|
959
990
|
},
|
|
960
991
|
)
|
|
961
|
-
time_mode =
|
|
962
|
-
Enum(
|
|
992
|
+
time_mode: Mapped[TimeMode] = mapped_column(
|
|
993
|
+
Enum(*get_args(TimeMode), native_enum=False),
|
|
963
994
|
default="disabled",
|
|
964
995
|
nullable=False,
|
|
965
996
|
info={
|
|
@@ -973,8 +1004,8 @@ class LayerWMS(DimensionLayer):
|
|
|
973
1004
|
}
|
|
974
1005
|
},
|
|
975
1006
|
)
|
|
976
|
-
time_widget =
|
|
977
|
-
Enum(
|
|
1007
|
+
time_widget: Mapped[TimeWidget] = mapped_column(
|
|
1008
|
+
Enum(*get_args(TimeWidget), native_enum=False),
|
|
978
1009
|
default="slider",
|
|
979
1010
|
nullable=False,
|
|
980
1011
|
info={
|
|
@@ -1005,8 +1036,8 @@ class LayerWMS(DimensionLayer):
|
|
|
1005
1036
|
name: str = "",
|
|
1006
1037
|
layer: str = "",
|
|
1007
1038
|
public: bool = True,
|
|
1008
|
-
time_mode:
|
|
1009
|
-
time_widget:
|
|
1039
|
+
time_mode: TimeMode = "disabled",
|
|
1040
|
+
time_widget: TimeWidget = "slider",
|
|
1010
1041
|
) -> None:
|
|
1011
1042
|
super().__init__(name=name, public=public)
|
|
1012
1043
|
self.layer = layer
|
|
@@ -1014,7 +1045,7 @@ class LayerWMS(DimensionLayer):
|
|
|
1014
1045
|
self.time_widget = time_widget
|
|
1015
1046
|
|
|
1016
1047
|
@staticmethod
|
|
1017
|
-
def get_default(dbsession: Session) ->
|
|
1048
|
+
def get_default(dbsession: Session) -> DimensionLayer | None:
|
|
1018
1049
|
return cast(
|
|
1019
1050
|
Optional[DimensionLayer],
|
|
1020
1051
|
dbsession.query(LayerWMS).filter(LayerWMS.name == "wms-defaults").one_or_none(),
|
|
@@ -1029,7 +1060,7 @@ class LayerWMTS(DimensionLayer):
|
|
|
1029
1060
|
__colanderalchemy_config__ = {
|
|
1030
1061
|
"title": _("WMTS Layer"),
|
|
1031
1062
|
"plural": _("WMTS Layers"),
|
|
1032
|
-
"description": Literal(
|
|
1063
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1033
1064
|
_(
|
|
1034
1065
|
"""
|
|
1035
1066
|
<div class="help-block">
|
|
@@ -1077,15 +1108,15 @@ class LayerWMTS(DimensionLayer):
|
|
|
1077
1108
|
),
|
|
1078
1109
|
}
|
|
1079
1110
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
1080
|
-
__mapper_args__ = {"polymorphic_identity": "l_wmts"}
|
|
1111
|
+
__mapper_args__ = {"polymorphic_identity": "l_wmts"} # type: ignore[dict-item]
|
|
1081
1112
|
|
|
1082
|
-
id =
|
|
1113
|
+
id: Mapped[int] = mapped_column(
|
|
1083
1114
|
Integer,
|
|
1084
|
-
ForeignKey(_schema + ".layer.id"),
|
|
1115
|
+
ForeignKey(_schema + ".layer.id", ondelete="CASCADE"),
|
|
1085
1116
|
primary_key=True,
|
|
1086
1117
|
info={"colanderalchemy": {"missing": None, "widget": HiddenWidget()}},
|
|
1087
1118
|
)
|
|
1088
|
-
url =
|
|
1119
|
+
url: Mapped[str] = mapped_column(
|
|
1089
1120
|
Unicode,
|
|
1090
1121
|
nullable=False,
|
|
1091
1122
|
info={
|
|
@@ -1096,29 +1127,32 @@ class LayerWMTS(DimensionLayer):
|
|
|
1096
1127
|
}
|
|
1097
1128
|
},
|
|
1098
1129
|
)
|
|
1099
|
-
layer =
|
|
1130
|
+
layer: Mapped[str] = mapped_column(
|
|
1100
1131
|
Unicode,
|
|
1101
1132
|
nullable=False,
|
|
1102
1133
|
info={
|
|
1103
1134
|
"colanderalchemy": {
|
|
1104
1135
|
"title": _("WMTS layer name"),
|
|
1105
|
-
"description": _("The name of the WMTS layer to use"),
|
|
1136
|
+
"description": _("The name of the WMTS layer to use."),
|
|
1106
1137
|
"column": 2,
|
|
1107
1138
|
}
|
|
1108
1139
|
},
|
|
1109
1140
|
)
|
|
1110
|
-
style =
|
|
1141
|
+
style: Mapped[str] = mapped_column(
|
|
1111
1142
|
Unicode,
|
|
1143
|
+
nullable=True,
|
|
1112
1144
|
info={
|
|
1113
1145
|
"colanderalchemy": {
|
|
1114
1146
|
"title": _("Style"),
|
|
1115
1147
|
"description": _("The style to use; if not present, the default style is used."),
|
|
1116
1148
|
"column": 2,
|
|
1149
|
+
"missing": "",
|
|
1117
1150
|
}
|
|
1118
1151
|
},
|
|
1119
1152
|
)
|
|
1120
|
-
matrix_set =
|
|
1153
|
+
matrix_set: Mapped[str] = mapped_column(
|
|
1121
1154
|
Unicode,
|
|
1155
|
+
nullable=True,
|
|
1122
1156
|
info={
|
|
1123
1157
|
"colanderalchemy": {
|
|
1124
1158
|
"title": _("Matrix set"),
|
|
@@ -1127,34 +1161,35 @@ class LayerWMTS(DimensionLayer):
|
|
|
1127
1161
|
"left empty."
|
|
1128
1162
|
),
|
|
1129
1163
|
"column": 2,
|
|
1164
|
+
"missing": "",
|
|
1130
1165
|
}
|
|
1131
1166
|
},
|
|
1132
1167
|
)
|
|
1133
|
-
image_type =
|
|
1134
|
-
Enum(
|
|
1168
|
+
image_type: Mapped[ImageType] = mapped_column(
|
|
1169
|
+
Enum(*get_args(ImageType), native_enum=False),
|
|
1135
1170
|
nullable=False,
|
|
1136
1171
|
info={
|
|
1137
1172
|
"colanderalchemy": {
|
|
1138
1173
|
"title": _("Image type"),
|
|
1139
|
-
"description": Literal(
|
|
1174
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1140
1175
|
_(
|
|
1141
1176
|
"""
|
|
1142
|
-
The MIME type of the images (e.g.: <code>image/png</code>).
|
|
1177
|
+
The MIME type of the images (e.g.: <code>image/png</code>, <code>image/webp</code> is experimental).
|
|
1143
1178
|
"""
|
|
1144
1179
|
)
|
|
1145
1180
|
),
|
|
1146
1181
|
"column": 2,
|
|
1147
|
-
"widget": SelectWidget(values=((
|
|
1182
|
+
"widget": SelectWidget(values=list((e, e) for e in get_args(ImageType))),
|
|
1148
1183
|
}
|
|
1149
1184
|
},
|
|
1150
1185
|
)
|
|
1151
1186
|
|
|
1152
|
-
def __init__(self, name: str = "", public: bool = True, image_type:
|
|
1187
|
+
def __init__(self, name: str = "", public: bool = True, image_type: ImageType = "image/png") -> None:
|
|
1153
1188
|
super().__init__(name=name, public=public)
|
|
1154
1189
|
self.image_type = image_type
|
|
1155
1190
|
|
|
1156
1191
|
@staticmethod
|
|
1157
|
-
def get_default(dbsession: Session) ->
|
|
1192
|
+
def get_default(dbsession: Session) -> DimensionLayer | None:
|
|
1158
1193
|
return cast(
|
|
1159
1194
|
Optional[DimensionLayer],
|
|
1160
1195
|
dbsession.query(LayerWMTS).filter(LayerWMTS.name == "wmts-defaults").one_or_none(),
|
|
@@ -1190,6 +1225,58 @@ layer_ra = Table(
|
|
|
1190
1225
|
)
|
|
1191
1226
|
|
|
1192
1227
|
|
|
1228
|
+
class LayerCOG(Layer):
|
|
1229
|
+
"""The Cloud Optimized GeoTIFF layer table representation."""
|
|
1230
|
+
|
|
1231
|
+
__tablename__ = "layer_cog"
|
|
1232
|
+
__table_args__ = {"schema": _schema}
|
|
1233
|
+
__colanderalchemy_config__ = {
|
|
1234
|
+
"title": _("COG Layer"),
|
|
1235
|
+
"plural": _("COG Layers"),
|
|
1236
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1237
|
+
_(
|
|
1238
|
+
"""
|
|
1239
|
+
<div class="help-block">
|
|
1240
|
+
<p>Definition of a <code>COG Layer</code> (COG for
|
|
1241
|
+
<a href="https://www.cogeo.org/">Cloud Optimized GeoTIFF</a>).</p>
|
|
1242
|
+
<p>Note: The layer named <code>cog-defaults</code> contain the values
|
|
1243
|
+
used when a new <code>COG layer</code> is created.</p>
|
|
1244
|
+
</div>
|
|
1245
|
+
"""
|
|
1246
|
+
)
|
|
1247
|
+
),
|
|
1248
|
+
}
|
|
1249
|
+
__c2cgeoform_config__ = {"duplicate": True}
|
|
1250
|
+
__mapper_args__ = {"polymorphic_identity": "l_cog"} # type: ignore[dict-item]
|
|
1251
|
+
|
|
1252
|
+
id: Mapped[int] = mapped_column(
|
|
1253
|
+
Integer,
|
|
1254
|
+
ForeignKey(_schema + ".layer.id"),
|
|
1255
|
+
primary_key=True,
|
|
1256
|
+
info={"colanderalchemy": {"missing": None, "widget": HiddenWidget()}},
|
|
1257
|
+
)
|
|
1258
|
+
url: Mapped[str] = mapped_column(
|
|
1259
|
+
Unicode,
|
|
1260
|
+
nullable=False,
|
|
1261
|
+
info={
|
|
1262
|
+
"colanderalchemy": {
|
|
1263
|
+
"title": _("URL"),
|
|
1264
|
+
"description": _("URL of the COG file."),
|
|
1265
|
+
"column": 2,
|
|
1266
|
+
}
|
|
1267
|
+
},
|
|
1268
|
+
)
|
|
1269
|
+
|
|
1270
|
+
@staticmethod
|
|
1271
|
+
def get_default(dbsession: Session) -> Layer | None:
|
|
1272
|
+
return dbsession.query(LayerCOG).filter(LayerCOG.name == "cog-defaults").one_or_none()
|
|
1273
|
+
|
|
1274
|
+
def url_description(self, request: pyramid.request.Request) -> str:
|
|
1275
|
+
errors: set[str] = set()
|
|
1276
|
+
url = get_url2(self.name, self.url, request, errors)
|
|
1277
|
+
return url.url() if url else "\n".join(errors)
|
|
1278
|
+
|
|
1279
|
+
|
|
1193
1280
|
class LayerVectorTiles(DimensionLayer):
|
|
1194
1281
|
"""The layer_vectortiles table representation."""
|
|
1195
1282
|
|
|
@@ -1198,7 +1285,7 @@ class LayerVectorTiles(DimensionLayer):
|
|
|
1198
1285
|
__colanderalchemy_config__ = {
|
|
1199
1286
|
"title": _("Vector Tiles Layer"),
|
|
1200
1287
|
"plural": _("Vector Tiles Layers"),
|
|
1201
|
-
"description": Literal(
|
|
1288
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1202
1289
|
_(
|
|
1203
1290
|
"""
|
|
1204
1291
|
<div class="help-block">
|
|
@@ -1232,16 +1319,16 @@ class LayerVectorTiles(DimensionLayer):
|
|
|
1232
1319
|
|
|
1233
1320
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
1234
1321
|
|
|
1235
|
-
__mapper_args__ = {"polymorphic_identity": "l_mvt"}
|
|
1322
|
+
__mapper_args__ = {"polymorphic_identity": "l_mvt"} # type: ignore[dict-item]
|
|
1236
1323
|
|
|
1237
|
-
id =
|
|
1324
|
+
id: Mapped[int] = mapped_column(
|
|
1238
1325
|
Integer,
|
|
1239
1326
|
ForeignKey(_schema + ".layer.id"),
|
|
1240
1327
|
primary_key=True,
|
|
1241
1328
|
info={"colanderalchemy": {"missing": None, "widget": HiddenWidget()}},
|
|
1242
1329
|
)
|
|
1243
1330
|
|
|
1244
|
-
style =
|
|
1331
|
+
style: Mapped[str] = mapped_column(
|
|
1245
1332
|
Unicode,
|
|
1246
1333
|
nullable=False,
|
|
1247
1334
|
info={
|
|
@@ -1249,7 +1336,7 @@ class LayerVectorTiles(DimensionLayer):
|
|
|
1249
1336
|
"title": _("Style"),
|
|
1250
1337
|
"description": _(
|
|
1251
1338
|
"""
|
|
1252
|
-
The path to a Mapbox Style file (version 8 or higher). Example: https://url/style.json
|
|
1339
|
+
The path to a Mapbox Style file (version 8 or higher). Example: https://url/style.json.
|
|
1253
1340
|
"""
|
|
1254
1341
|
),
|
|
1255
1342
|
"column": 2,
|
|
@@ -1257,24 +1344,20 @@ class LayerVectorTiles(DimensionLayer):
|
|
|
1257
1344
|
},
|
|
1258
1345
|
)
|
|
1259
1346
|
|
|
1260
|
-
sql =
|
|
1347
|
+
sql: Mapped[str] = mapped_column(
|
|
1261
1348
|
Unicode,
|
|
1262
1349
|
nullable=True,
|
|
1263
1350
|
info={
|
|
1264
1351
|
"colanderalchemy": {
|
|
1265
1352
|
"title": _("SQL query"),
|
|
1266
|
-
"description": _(
|
|
1267
|
-
"""
|
|
1268
|
-
A SQL query to get the vector tiles data.
|
|
1269
|
-
"""
|
|
1270
|
-
),
|
|
1353
|
+
"description": _("An SQL query to retrieve the vector tiles data."),
|
|
1271
1354
|
"column": 2,
|
|
1272
1355
|
"widget": TextAreaWidget(rows=15),
|
|
1273
1356
|
}
|
|
1274
1357
|
},
|
|
1275
1358
|
)
|
|
1276
1359
|
|
|
1277
|
-
xyz =
|
|
1360
|
+
xyz: Mapped[str] = mapped_column(
|
|
1278
1361
|
Unicode,
|
|
1279
1362
|
nullable=True,
|
|
1280
1363
|
info={
|
|
@@ -1297,7 +1380,7 @@ class LayerVectorTiles(DimensionLayer):
|
|
|
1297
1380
|
self.sql = sql
|
|
1298
1381
|
|
|
1299
1382
|
@staticmethod
|
|
1300
|
-
def get_default(dbsession: Session) ->
|
|
1383
|
+
def get_default(dbsession: Session) -> DimensionLayer | None:
|
|
1301
1384
|
return cast(
|
|
1302
1385
|
Optional[DimensionLayer],
|
|
1303
1386
|
dbsession.query(LayerVectorTiles)
|
|
@@ -1306,7 +1389,7 @@ class LayerVectorTiles(DimensionLayer):
|
|
|
1306
1389
|
)
|
|
1307
1390
|
|
|
1308
1391
|
def style_description(self, request: pyramid.request.Request) -> str:
|
|
1309
|
-
errors:
|
|
1392
|
+
errors: set[str] = set()
|
|
1310
1393
|
url = get_url2(self.name, self.style, request, errors)
|
|
1311
1394
|
return url.url() if url else "\n".join(errors)
|
|
1312
1395
|
|
|
@@ -1318,9 +1401,11 @@ class RestrictionArea(Base): # type: ignore
|
|
|
1318
1401
|
__table_args__ = {"schema": _schema}
|
|
1319
1402
|
__colanderalchemy_config__ = {"title": _("Restriction area"), "plural": _("Restriction areas")}
|
|
1320
1403
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
1321
|
-
id
|
|
1404
|
+
id: Mapped[int] = mapped_column(
|
|
1405
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
1406
|
+
)
|
|
1322
1407
|
|
|
1323
|
-
name =
|
|
1408
|
+
name: Mapped[str] = mapped_column(
|
|
1324
1409
|
Unicode,
|
|
1325
1410
|
info={
|
|
1326
1411
|
"colanderalchemy": {
|
|
@@ -1329,16 +1414,16 @@ class RestrictionArea(Base): # type: ignore
|
|
|
1329
1414
|
}
|
|
1330
1415
|
},
|
|
1331
1416
|
)
|
|
1332
|
-
description =
|
|
1417
|
+
description: Mapped[str | None] = mapped_column(
|
|
1333
1418
|
Unicode,
|
|
1334
1419
|
info={
|
|
1335
1420
|
"colanderalchemy": {
|
|
1336
1421
|
"title": _("Description"),
|
|
1337
|
-
"description": _("An optional description"),
|
|
1422
|
+
"description": _("An optional description."),
|
|
1338
1423
|
}
|
|
1339
1424
|
},
|
|
1340
1425
|
)
|
|
1341
|
-
readwrite =
|
|
1426
|
+
readwrite: Mapped[bool] = mapped_column(
|
|
1342
1427
|
Boolean,
|
|
1343
1428
|
default=False,
|
|
1344
1429
|
info={
|
|
@@ -1348,7 +1433,7 @@ class RestrictionArea(Base): # type: ignore
|
|
|
1348
1433
|
}
|
|
1349
1434
|
},
|
|
1350
1435
|
)
|
|
1351
|
-
area =
|
|
1436
|
+
area = mapped_column(
|
|
1352
1437
|
Geometry("POLYGON", srid=_srid),
|
|
1353
1438
|
info={
|
|
1354
1439
|
"colanderalchemy": {
|
|
@@ -1393,7 +1478,7 @@ class RestrictionArea(Base): # type: ignore
|
|
|
1393
1478
|
"colanderalchemy": {
|
|
1394
1479
|
"title": _("Layers"),
|
|
1395
1480
|
"exclude": True,
|
|
1396
|
-
"description": Literal(
|
|
1481
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1397
1482
|
_(
|
|
1398
1483
|
"""
|
|
1399
1484
|
<div class="help-block">
|
|
@@ -1422,9 +1507,9 @@ class RestrictionArea(Base): # type: ignore
|
|
|
1422
1507
|
self,
|
|
1423
1508
|
name: str = "",
|
|
1424
1509
|
description: str = "",
|
|
1425
|
-
layers:
|
|
1426
|
-
roles:
|
|
1427
|
-
area: Geometry = None,
|
|
1510
|
+
layers: list[Layer] | None = None,
|
|
1511
|
+
roles: list[Role] | None = None,
|
|
1512
|
+
area: Geometry | None = None,
|
|
1428
1513
|
readwrite: bool = False,
|
|
1429
1514
|
) -> None:
|
|
1430
1515
|
if layers is None:
|
|
@@ -1478,8 +1563,10 @@ class Interface(Base): # type: ignore
|
|
|
1478
1563
|
__c2cgeoform_config__ = {"duplicate": True}
|
|
1479
1564
|
__colanderalchemy_config__ = {"title": _("Interface"), "plural": _("Interfaces")}
|
|
1480
1565
|
|
|
1481
|
-
id
|
|
1482
|
-
|
|
1566
|
+
id: Mapped[int] = mapped_column(
|
|
1567
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
1568
|
+
)
|
|
1569
|
+
name: Mapped[str] = mapped_column(
|
|
1483
1570
|
Unicode,
|
|
1484
1571
|
info={
|
|
1485
1572
|
"colanderalchemy": {
|
|
@@ -1488,7 +1575,7 @@ class Interface(Base): # type: ignore
|
|
|
1488
1575
|
}
|
|
1489
1576
|
},
|
|
1490
1577
|
)
|
|
1491
|
-
description =
|
|
1578
|
+
description: Mapped[str | None] = mapped_column(
|
|
1492
1579
|
Unicode,
|
|
1493
1580
|
info={
|
|
1494
1581
|
"colanderalchemy": {
|
|
@@ -1550,18 +1637,23 @@ class Metadata(Base): # type: ignore
|
|
|
1550
1637
|
"plural": _("Metadatas"),
|
|
1551
1638
|
}
|
|
1552
1639
|
|
|
1553
|
-
id
|
|
1554
|
-
|
|
1640
|
+
id: Mapped[int] = mapped_column(
|
|
1641
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
1642
|
+
)
|
|
1643
|
+
name: Mapped[str] = mapped_column(
|
|
1555
1644
|
Unicode,
|
|
1556
1645
|
info={
|
|
1557
1646
|
"colanderalchemy": {
|
|
1558
1647
|
"title": _("Name"),
|
|
1559
|
-
"description": Literal(
|
|
1648
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1649
|
+
_("The type of <code>Metadata</code> we want to set.")
|
|
1650
|
+
),
|
|
1560
1651
|
}
|
|
1561
1652
|
},
|
|
1562
1653
|
)
|
|
1563
|
-
value =
|
|
1654
|
+
value: Mapped[str] = mapped_column(
|
|
1564
1655
|
Unicode,
|
|
1656
|
+
nullable=True,
|
|
1565
1657
|
info={
|
|
1566
1658
|
"colanderalchemy": {
|
|
1567
1659
|
"title": _("Value"),
|
|
@@ -1570,7 +1662,7 @@ class Metadata(Base): # type: ignore
|
|
|
1570
1662
|
}
|
|
1571
1663
|
},
|
|
1572
1664
|
)
|
|
1573
|
-
description =
|
|
1665
|
+
description: Mapped[str | None] = mapped_column(
|
|
1574
1666
|
Unicode,
|
|
1575
1667
|
info={
|
|
1576
1668
|
"colanderalchemy": {
|
|
@@ -1581,10 +1673,10 @@ class Metadata(Base): # type: ignore
|
|
|
1581
1673
|
},
|
|
1582
1674
|
)
|
|
1583
1675
|
|
|
1584
|
-
item_id =
|
|
1676
|
+
item_id: Mapped[int] = mapped_column(
|
|
1585
1677
|
"item_id",
|
|
1586
1678
|
Integer,
|
|
1587
|
-
ForeignKey(_schema + ".treeitem.id"),
|
|
1679
|
+
ForeignKey(_schema + ".treeitem.id", ondelete="CASCADE"),
|
|
1588
1680
|
nullable=False,
|
|
1589
1681
|
info={"colanderalchemy": {"exclude": True}, "c2cgeoform": {"duplicate": False}},
|
|
1590
1682
|
)
|
|
@@ -1598,7 +1690,7 @@ class Metadata(Base): # type: ignore
|
|
|
1598
1690
|
info={
|
|
1599
1691
|
"colanderalchemy": {
|
|
1600
1692
|
"title": _("Metadatas"),
|
|
1601
|
-
"description": Literal(
|
|
1693
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1602
1694
|
_(
|
|
1603
1695
|
"""
|
|
1604
1696
|
<div class="help-block">
|
|
@@ -1631,7 +1723,7 @@ class Metadata(Base): # type: ignore
|
|
|
1631
1723
|
),
|
|
1632
1724
|
)
|
|
1633
1725
|
|
|
1634
|
-
def __init__(self, name: str = "", value: str = "", description:
|
|
1726
|
+
def __init__(self, name: str = "", value: str = "", description: str | None = None) -> None:
|
|
1635
1727
|
self.name = name
|
|
1636
1728
|
self.value = value
|
|
1637
1729
|
self.description = description
|
|
@@ -1655,8 +1747,10 @@ class Dimension(Base): # type: ignore
|
|
|
1655
1747
|
"plural": _("Dimensions"),
|
|
1656
1748
|
}
|
|
1657
1749
|
|
|
1658
|
-
id
|
|
1659
|
-
|
|
1750
|
+
id: Mapped[int] = mapped_column(
|
|
1751
|
+
Integer, primary_key=True, info={"colanderalchemy": {"widget": HiddenWidget()}}
|
|
1752
|
+
)
|
|
1753
|
+
name: Mapped[str] = mapped_column(
|
|
1660
1754
|
Unicode,
|
|
1661
1755
|
info={
|
|
1662
1756
|
"colanderalchemy": {
|
|
@@ -1665,8 +1759,9 @@ class Dimension(Base): # type: ignore
|
|
|
1665
1759
|
}
|
|
1666
1760
|
},
|
|
1667
1761
|
)
|
|
1668
|
-
value =
|
|
1762
|
+
value: Mapped[str] = mapped_column(
|
|
1669
1763
|
Unicode,
|
|
1764
|
+
nullable=True,
|
|
1670
1765
|
info={
|
|
1671
1766
|
"colanderalchemy": {
|
|
1672
1767
|
"title": _("Value"),
|
|
@@ -1674,7 +1769,7 @@ class Dimension(Base): # type: ignore
|
|
|
1674
1769
|
}
|
|
1675
1770
|
},
|
|
1676
1771
|
)
|
|
1677
|
-
field =
|
|
1772
|
+
field: Mapped[str | None] = mapped_column(
|
|
1678
1773
|
Unicode,
|
|
1679
1774
|
info={
|
|
1680
1775
|
"colanderalchemy": {
|
|
@@ -1685,7 +1780,7 @@ class Dimension(Base): # type: ignore
|
|
|
1685
1780
|
}
|
|
1686
1781
|
},
|
|
1687
1782
|
)
|
|
1688
|
-
description =
|
|
1783
|
+
description: Mapped[str | None] = mapped_column(
|
|
1689
1784
|
Unicode,
|
|
1690
1785
|
info={
|
|
1691
1786
|
"colanderalchemy": {
|
|
@@ -1696,7 +1791,7 @@ class Dimension(Base): # type: ignore
|
|
|
1696
1791
|
},
|
|
1697
1792
|
)
|
|
1698
1793
|
|
|
1699
|
-
layer_id =
|
|
1794
|
+
layer_id: Mapped[int] = mapped_column(
|
|
1700
1795
|
"layer_id",
|
|
1701
1796
|
Integer,
|
|
1702
1797
|
ForeignKey(_schema + ".layer.id"),
|
|
@@ -1713,7 +1808,7 @@ class Dimension(Base): # type: ignore
|
|
|
1713
1808
|
"colanderalchemy": {
|
|
1714
1809
|
"title": _("Dimensions"),
|
|
1715
1810
|
"exclude": True,
|
|
1716
|
-
"description": Literal(
|
|
1811
|
+
"description": c2cgeoportal_commons.lib.literal.Literal(
|
|
1717
1812
|
_(
|
|
1718
1813
|
"""
|
|
1719
1814
|
<div class="help-block">
|
|
@@ -1732,9 +1827,9 @@ class Dimension(Base): # type: ignore
|
|
|
1732
1827
|
self,
|
|
1733
1828
|
name: str = "",
|
|
1734
1829
|
value: str = "",
|
|
1735
|
-
layer:
|
|
1736
|
-
field:
|
|
1737
|
-
description:
|
|
1830
|
+
layer: str | None = None,
|
|
1831
|
+
field: str | None = None,
|
|
1832
|
+
description: str | None = None,
|
|
1738
1833
|
) -> None:
|
|
1739
1834
|
self.name = name
|
|
1740
1835
|
self.value = value
|
|
@@ -1767,8 +1862,8 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1767
1862
|
"plural": _("Logs"),
|
|
1768
1863
|
}
|
|
1769
1864
|
|
|
1770
|
-
id =
|
|
1771
|
-
date =
|
|
1865
|
+
id: Mapped[int] = mapped_column(Integer, primary_key=True, info={"colanderalchemy": {}})
|
|
1866
|
+
date: Mapped[datetime] = mapped_column(
|
|
1772
1867
|
DateTime(timezone=True),
|
|
1773
1868
|
nullable=False,
|
|
1774
1869
|
info={
|
|
@@ -1777,7 +1872,7 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1777
1872
|
}
|
|
1778
1873
|
},
|
|
1779
1874
|
)
|
|
1780
|
-
action =
|
|
1875
|
+
action: Mapped[LogAction] = mapped_column(
|
|
1781
1876
|
Enum(LogAction, native_enum=False),
|
|
1782
1877
|
nullable=False,
|
|
1783
1878
|
info={
|
|
@@ -1786,7 +1881,7 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1786
1881
|
}
|
|
1787
1882
|
},
|
|
1788
1883
|
)
|
|
1789
|
-
element_type =
|
|
1884
|
+
element_type: Mapped[str] = mapped_column(
|
|
1790
1885
|
String(50),
|
|
1791
1886
|
nullable=False,
|
|
1792
1887
|
info={
|
|
@@ -1795,7 +1890,7 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1795
1890
|
}
|
|
1796
1891
|
},
|
|
1797
1892
|
)
|
|
1798
|
-
element_id =
|
|
1893
|
+
element_id: Mapped[int] = mapped_column(
|
|
1799
1894
|
Integer,
|
|
1800
1895
|
nullable=False,
|
|
1801
1896
|
info={
|
|
@@ -1804,7 +1899,7 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1804
1899
|
}
|
|
1805
1900
|
},
|
|
1806
1901
|
)
|
|
1807
|
-
element_name =
|
|
1902
|
+
element_name: Mapped[str] = mapped_column(
|
|
1808
1903
|
Unicode,
|
|
1809
1904
|
nullable=False,
|
|
1810
1905
|
info={
|
|
@@ -1813,7 +1908,7 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1813
1908
|
}
|
|
1814
1909
|
},
|
|
1815
1910
|
)
|
|
1816
|
-
element_url_table =
|
|
1911
|
+
element_url_table: Mapped[str] = mapped_column(
|
|
1817
1912
|
Unicode,
|
|
1818
1913
|
nullable=False,
|
|
1819
1914
|
info={
|
|
@@ -1822,7 +1917,7 @@ class AbstractLog(AbstractConcreteBase, Base): # type: ignore
|
|
|
1822
1917
|
}
|
|
1823
1918
|
},
|
|
1824
1919
|
)
|
|
1825
|
-
username =
|
|
1920
|
+
username: Mapped[str] = mapped_column(
|
|
1826
1921
|
Unicode,
|
|
1827
1922
|
nullable=False,
|
|
1828
1923
|
info={
|