c2cgeoportal-admin 2.6.0__py3-none-any.whl → 2.8.1.180__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_admin/__init__.py +32 -10
- c2cgeoportal_admin/lib/lingua_extractor.py +77 -0
- c2cgeoportal_admin/lib/ogcserver_synchronizer.py +168 -56
- c2cgeoportal_admin/py.typed +0 -0
- c2cgeoportal_admin/routes.py +7 -4
- c2cgeoportal_admin/schemas/dimensions.py +12 -10
- c2cgeoportal_admin/schemas/functionalities.py +62 -21
- c2cgeoportal_admin/schemas/interfaces.py +22 -18
- c2cgeoportal_admin/schemas/metadata.py +100 -47
- c2cgeoportal_admin/schemas/restriction_areas.py +21 -19
- c2cgeoportal_admin/schemas/roles.py +7 -5
- c2cgeoportal_admin/schemas/treegroup.py +38 -17
- c2cgeoportal_admin/schemas/treeitem.py +2 -3
- c2cgeoportal_admin/static/layertree.css +3 -4
- c2cgeoportal_admin/static/navbar.css +36 -35
- c2cgeoportal_admin/static/theme.css +16 -9
- c2cgeoportal_admin/subscribers.py +3 -3
- c2cgeoportal_admin/templates/404.jinja2 +18 -2
- c2cgeoportal_admin/templates/layertree.jinja2 +31 -9
- c2cgeoportal_admin/templates/navigation_navbar.jinja2 +33 -0
- c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +12 -0
- c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
- c2cgeoportal_admin/templates/widgets/metadata.pt +7 -1
- c2cgeoportal_admin/views/__init__.py +29 -0
- c2cgeoportal_admin/views/dimension_layers.py +7 -6
- c2cgeoportal_admin/views/functionalities.py +33 -6
- c2cgeoportal_admin/views/home.py +5 -5
- c2cgeoportal_admin/views/interfaces.py +7 -8
- c2cgeoportal_admin/views/layer_groups.py +9 -11
- c2cgeoportal_admin/views/layers.py +8 -7
- c2cgeoportal_admin/views/layers_vectortiles.py +30 -10
- c2cgeoportal_admin/views/layers_wms.py +41 -35
- c2cgeoportal_admin/views/layers_wmts.py +41 -35
- c2cgeoportal_admin/views/layertree.py +36 -28
- c2cgeoportal_admin/views/logged_views.py +80 -0
- c2cgeoportal_admin/views/logs.py +90 -0
- c2cgeoportal_admin/views/oauth2_clients.py +30 -22
- c2cgeoportal_admin/views/ogc_servers.py +119 -37
- c2cgeoportal_admin/views/restriction_areas.py +13 -11
- c2cgeoportal_admin/views/roles.py +16 -12
- c2cgeoportal_admin/views/themes.py +15 -14
- c2cgeoportal_admin/views/themes_ordering.py +13 -8
- c2cgeoportal_admin/views/treeitems.py +14 -12
- c2cgeoportal_admin/views/users.py +12 -7
- c2cgeoportal_admin/widgets.py +17 -14
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/METADATA +17 -8
- c2cgeoportal_admin-2.8.1.180.dist-info/RECORD +95 -0
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/WHEEL +1 -1
- c2cgeoportal_admin-2.8.1.180.dist-info/entry_points.txt +6 -0
- tests/__init__.py +11 -12
- tests/conftest.py +2 -1
- tests/test_edit_url.py +11 -14
- tests/test_functionalities.py +52 -14
- tests/test_home.py +0 -1
- tests/test_interface.py +34 -11
- tests/test_layer_groups.py +57 -27
- tests/test_layers_vectortiles.py +43 -20
- tests/test_layers_wms.py +67 -45
- tests/test_layers_wmts.py +47 -26
- tests/test_layertree.py +99 -16
- tests/test_left_menu.py +0 -1
- tests/test_lingua_extractor_config.py +64 -0
- tests/test_logs.py +103 -0
- tests/test_main.py +3 -1
- tests/test_metadatas.py +34 -21
- tests/test_oauth2_clients.py +37 -9
- tests/test_ogc_servers.py +84 -35
- tests/test_restriction_areas.py +38 -15
- tests/test_role.py +68 -41
- tests/test_themes.py +71 -37
- tests/test_themes_ordering.py +1 -2
- tests/test_treegroup.py +2 -2
- tests/test_user.py +48 -17
- tests/themes_ordering.py +1 -2
- c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -33
- c2cgeoportal_admin-2.6.0.dist-info/RECORD +0 -89
- c2cgeoportal_admin-2.6.0.dist-info/entry_points.txt +0 -3
- {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2017-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2017-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -41,7 +39,9 @@ from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
|
|
41
39
|
from c2cgeoportal_commons.models.main import Theme, TreeItem
|
42
40
|
|
43
41
|
|
44
|
-
class ThemeOrderSchema(GeoFormSchemaNode): # pylint: disable=abstract-method
|
42
|
+
class ThemeOrderSchema(GeoFormSchemaNode): # type: ignore # pylint: disable=abstract-method
|
43
|
+
"""The theme order schema."""
|
44
|
+
|
45
45
|
def objectify(self, dict_, context=None):
|
46
46
|
context = self.dbsession.query(Theme).get(dict_["id"])
|
47
47
|
context = super().objectify(dict_, context)
|
@@ -50,14 +50,16 @@ class ThemeOrderSchema(GeoFormSchemaNode): # pylint: disable=abstract-method
|
|
50
50
|
|
51
51
|
@colander.deferred
|
52
52
|
def themes(node, kw): # pylint: disable=unused-argument
|
53
|
+
"""Get some theme metadata."""
|
53
54
|
query = kw["dbsession"].query(Theme).order_by(Theme.ordering, Theme.name)
|
54
55
|
return [
|
55
|
-
{"id": item.id, "label": item.name, "icon_class": "icon-{
|
56
|
+
{"id": item.id, "label": item.name, "icon_class": f"icon-{item.item_type}", "group": "All"}
|
56
57
|
for item in query
|
57
58
|
]
|
58
59
|
|
59
60
|
|
60
61
|
def themes_validator(node, cstruct):
|
62
|
+
"""Validate the theme."""
|
61
63
|
for dict_ in cstruct:
|
62
64
|
if not dict_["id"] in [item["id"] for item in node.candidates]:
|
63
65
|
raise colander.Invalid(
|
@@ -66,7 +68,9 @@ def themes_validator(node, cstruct):
|
|
66
68
|
)
|
67
69
|
|
68
70
|
|
69
|
-
class ThemesOrderingSchema(colander.MappingSchema):
|
71
|
+
class ThemesOrderingSchema(colander.MappingSchema): # type: ignore
|
72
|
+
"""The theme ordering schema."""
|
73
|
+
|
70
74
|
themes = colander.SequenceSchema(
|
71
75
|
ThemeOrderSchema(
|
72
76
|
Theme,
|
@@ -76,7 +80,7 @@ class ThemesOrderingSchema(colander.MappingSchema):
|
|
76
80
|
input_name="id",
|
77
81
|
model=TreeItem,
|
78
82
|
label_field="name",
|
79
|
-
icon_class=lambda item: "icon-{
|
83
|
+
icon_class=lambda item: f"icon-{item.item_type}",
|
80
84
|
edit_url=treeitem_edit_url,
|
81
85
|
),
|
82
86
|
),
|
@@ -87,7 +91,8 @@ class ThemesOrderingSchema(colander.MappingSchema):
|
|
87
91
|
)
|
88
92
|
|
89
93
|
|
90
|
-
class ThemesOrdering(AbstractViews):
|
94
|
+
class ThemesOrdering(AbstractViews): # type: ignore
|
95
|
+
"""The theme ordering admin view."""
|
91
96
|
|
92
97
|
_base_schema = ThemesOrderingSchema()
|
93
98
|
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2017-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2017-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -30,17 +28,21 @@
|
|
30
28
|
|
31
29
|
from functools import partial
|
32
30
|
|
33
|
-
|
31
|
+
import sqlalchemy
|
32
|
+
from c2cgeoform.views.abstract_views import ListField
|
34
33
|
from pyramid.view import view_config
|
35
34
|
from sqlalchemy.orm import subqueryload
|
36
35
|
from sqlalchemy.sql.functions import concat
|
37
36
|
|
37
|
+
from c2cgeoportal_admin.views.logged_views import LoggedViews
|
38
38
|
from c2cgeoportal_commons.models.main import LayergroupTreeitem, Metadata, TreeGroup, TreeItem
|
39
39
|
|
40
40
|
_list_field = partial(ListField, TreeItem)
|
41
41
|
|
42
42
|
|
43
|
-
class TreeItemViews(
|
43
|
+
class TreeItemViews(LoggedViews):
|
44
|
+
"""The admin tree item view."""
|
45
|
+
|
44
46
|
_list_fields = [
|
45
47
|
_list_field("id"),
|
46
48
|
_list_field("name"),
|
@@ -50,9 +52,7 @@ class TreeItemViews(AbstractViews):
|
|
50
52
|
_extra_list_fields_no_parents = [
|
51
53
|
_list_field(
|
52
54
|
"metadatas",
|
53
|
-
renderer=lambda
|
54
|
-
["{}: {}".format(m.name, m.value) or "" for m in layers_group.metadatas]
|
55
|
-
),
|
55
|
+
renderer=lambda treeitem: ", ".join([f"{m.name}: {m.value}" or "" for m in treeitem.metadatas]),
|
56
56
|
filter_column=concat(Metadata.name, ": ", Metadata.value).label("metadata"),
|
57
57
|
)
|
58
58
|
]
|
@@ -72,16 +72,18 @@ class TreeItemViews(AbstractViews):
|
|
72
72
|
def save(self):
|
73
73
|
response = super().save()
|
74
74
|
# correctly handles the validation error as if there is a validation error, cstruct is empty
|
75
|
-
|
75
|
+
has_to_be_registered_in_parent = (
|
76
76
|
hasattr(self, "_appstruct") and self._appstruct is not None and self._appstruct.get("parent_id")
|
77
77
|
)
|
78
|
-
if
|
79
|
-
parent = self._request.dbsession.query(TreeGroup).get(
|
78
|
+
if has_to_be_registered_in_parent:
|
79
|
+
parent = self._request.dbsession.query(TreeGroup).get(has_to_be_registered_in_parent)
|
80
80
|
rel = LayergroupTreeitem(parent, self._obj, 100)
|
81
81
|
self._request.dbsession.add(rel)
|
82
82
|
return response
|
83
83
|
|
84
|
-
def _base_query(
|
84
|
+
def _base_query( # pylint: disable=arguments-differ
|
85
|
+
self, query: sqlalchemy.orm.query.Query
|
86
|
+
) -> sqlalchemy.orm.query.Query:
|
85
87
|
return (
|
86
88
|
query.outerjoin("metadatas")
|
87
89
|
.options(subqueryload("parents_relation").joinedload("treegroup"))
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2017-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2017-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -31,7 +29,7 @@
|
|
31
29
|
from functools import partial
|
32
30
|
|
33
31
|
from c2cgeoform.schema import GeoFormSchemaNode
|
34
|
-
from c2cgeoform.views.abstract_views import
|
32
|
+
from c2cgeoform.views.abstract_views import ListField
|
35
33
|
from deform.widget import FormWidget
|
36
34
|
from passwordgenerator import pwgenerator
|
37
35
|
from pyramid.httpexceptions import HTTPFound
|
@@ -39,21 +37,24 @@ from pyramid.view import view_config, view_defaults
|
|
39
37
|
from sqlalchemy.orm import aliased, subqueryload
|
40
38
|
|
41
39
|
from c2cgeoportal_admin.schemas.roles import roles_schema_node
|
40
|
+
from c2cgeoportal_admin.views.logged_views import LoggedViews
|
42
41
|
from c2cgeoportal_commons.lib.email_ import send_email_config
|
43
42
|
from c2cgeoportal_commons.models.main import Role
|
44
|
-
from c2cgeoportal_commons.models.static import User
|
43
|
+
from c2cgeoportal_commons.models.static import Log, User
|
45
44
|
|
46
45
|
_list_field = partial(ListField, User)
|
47
46
|
|
48
47
|
base_schema = GeoFormSchemaNode(User, widget=FormWidget(fields_template="user_fields"))
|
49
|
-
base_schema.add(roles_schema_node(
|
48
|
+
base_schema.add(roles_schema_node(User.roles))
|
50
49
|
base_schema.add_unique_validator(User.username, User.id)
|
51
50
|
|
52
51
|
settings_role = aliased(Role)
|
53
52
|
|
54
53
|
|
55
54
|
@view_defaults(match_param="table=users")
|
56
|
-
class UserViews(
|
55
|
+
class UserViews(LoggedViews):
|
56
|
+
"""The admin user view."""
|
57
|
+
|
57
58
|
_list_fields = [
|
58
59
|
_list_field("id"),
|
59
60
|
_list_field("username"),
|
@@ -76,6 +77,8 @@ class UserViews(AbstractViews):
|
|
76
77
|
_id_field = "id"
|
77
78
|
_model = User
|
78
79
|
_base_schema = base_schema
|
80
|
+
_log_model = Log
|
81
|
+
_name_field = "username"
|
79
82
|
|
80
83
|
def _base_query(self):
|
81
84
|
return (
|
@@ -119,6 +122,8 @@ class UserViews(AbstractViews):
|
|
119
122
|
email=user.email,
|
120
123
|
user=user.username,
|
121
124
|
password=password,
|
125
|
+
application_url=self._request.route_url("base"),
|
126
|
+
current_url=self._request.current_route_url(),
|
122
127
|
)
|
123
128
|
|
124
129
|
return response
|
c2cgeoportal_admin/widgets.py
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2018-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2018-2024, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -27,9 +25,10 @@
|
|
27
25
|
# of the authors and should not be interpreted as representing official policies,
|
28
26
|
# either expressed or implied, of the FreeBSD Project.
|
29
27
|
|
30
|
-
from typing import Optional
|
28
|
+
from typing import Any, Optional
|
31
29
|
|
32
30
|
import colander
|
31
|
+
import pyramid.request
|
33
32
|
from colander import Mapping, SchemaNode
|
34
33
|
from deform import widget
|
35
34
|
from deform.widget import MappingWidget, SequenceWidget
|
@@ -55,10 +54,11 @@ widget.DateTimeInputWidget._pstruct_schema = SchemaNode( # pylint: disable=prot
|
|
55
54
|
)
|
56
55
|
|
57
56
|
|
58
|
-
class ChildWidget(MappingWidget):
|
57
|
+
class ChildWidget(MappingWidget): # type: ignore
|
59
58
|
"""
|
60
|
-
Extension of the widget ````deform.widget.MappingWidget
|
61
|
-
|
59
|
+
Extension of the widget ````deform.widget.MappingWidget``.
|
60
|
+
|
61
|
+
To be used in conjunction with ChildrenWidget, to manage n-m relationships.
|
62
62
|
|
63
63
|
Do not embed complete children forms, but just an hidden input for child primary key.
|
64
64
|
|
@@ -82,7 +82,7 @@ class ChildWidget(MappingWidget):
|
|
82
82
|
|
83
83
|
For further attributes, please refer to the documentation of
|
84
84
|
``deform.widget.MappingWidget`` in the deform documentation:
|
85
|
-
<
|
85
|
+
<https://deform.readthedocs.org/en/latest/api.html>
|
86
86
|
"""
|
87
87
|
|
88
88
|
template = "child"
|
@@ -90,11 +90,13 @@ class ChildWidget(MappingWidget):
|
|
90
90
|
model = TreeItem
|
91
91
|
label_field = "name"
|
92
92
|
|
93
|
-
def icon_class(self, child) -> Optional[str]: # pylint: disable=
|
93
|
+
def icon_class(self, child: Any) -> Optional[str]: # pylint: disable=useless-return
|
94
94
|
del child
|
95
95
|
return None
|
96
96
|
|
97
|
-
def edit_url(
|
97
|
+
def edit_url( # pylint: disable=useless-return
|
98
|
+
self, request: pyramid.request.Request, child: Any
|
99
|
+
) -> Optional[str]:
|
98
100
|
del request
|
99
101
|
del child
|
100
102
|
return None
|
@@ -107,10 +109,11 @@ class ChildWidget(MappingWidget):
|
|
107
109
|
return super().serialize(field, cstruct, **kw)
|
108
110
|
|
109
111
|
|
110
|
-
class ChildrenWidget(SequenceWidget):
|
112
|
+
class ChildrenWidget(SequenceWidget): # type: ignore
|
111
113
|
"""
|
112
|
-
Extension of the widget ````deform.widget.SequenceWidget
|
113
|
-
|
114
|
+
Extension of the widget ````deform.widget.SequenceWidget``.
|
115
|
+
|
116
|
+
To be used in conjunction with ChildWidget, to manage n-m relationships.
|
114
117
|
|
115
118
|
Use Magicsuggest for searching into parent schema candidates property, which should be a list of
|
116
119
|
dictionaries of the form:
|
@@ -129,7 +132,7 @@ class ChildrenWidget(SequenceWidget):
|
|
129
132
|
|
130
133
|
For further attributes, please refer to the documentation of
|
131
134
|
``deform.widget.SequenceWidget`` in the deform documentation:
|
132
|
-
<
|
135
|
+
<https://deform.readthedocs.org/en/latest/api.html>
|
133
136
|
"""
|
134
137
|
|
135
138
|
template = "children"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: c2cgeoportal-admin
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.8.1.180
|
4
4
|
Summary: c2cgeoportal admin
|
5
5
|
Home-page: https://github.com/camptocamp/c2cgeoportal/
|
6
6
|
Author: Camptocamp
|
@@ -8,27 +8,36 @@ Author-email: info@camptocamp.com
|
|
8
8
|
License: UNKNOWN
|
9
9
|
Keywords: web gis geoportail c2cgeoportal geocommune pyramid
|
10
10
|
Platform: UNKNOWN
|
11
|
-
Classifier:
|
12
|
-
Classifier:
|
13
|
-
Classifier: Programming Language :: Python :: 3.7
|
11
|
+
Classifier: Development Status :: 6 - Mature
|
12
|
+
Classifier: Environment :: Web Environment
|
14
13
|
Classifier: Framework :: Pyramid
|
15
|
-
Classifier:
|
16
|
-
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
14
|
+
Classifier: Intended Audience :: Other Audience
|
17
15
|
Classifier: License :: OSI Approved :: BSD License
|
18
|
-
Classifier:
|
16
|
+
Classifier: Operating System :: OS Independent
|
17
|
+
Classifier: Programming Language :: Python
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
21
|
+
Classifier: Typing :: Typed
|
19
22
|
Description-Content-Type: text/markdown
|
23
|
+
Requires-Dist: babel (>=2.9.1)
|
20
24
|
Requires-Dist: c2cgeoform
|
21
25
|
Requires-Dist: c2cwsgiutils
|
26
|
+
Requires-Dist: certifi (>=2022.12.7)
|
22
27
|
Requires-Dist: colander
|
23
28
|
Requires-Dist: deform
|
29
|
+
Requires-Dist: idna (>=3.7)
|
24
30
|
Requires-Dist: passwordgenerator
|
31
|
+
Requires-Dist: pygments (>=2.15.0)
|
25
32
|
Requires-Dist: pyproj
|
26
33
|
Requires-Dist: pyramid
|
27
34
|
Requires-Dist: pyramid-debugtoolbar
|
28
35
|
Requires-Dist: pyramid-jinja2
|
29
36
|
Requires-Dist: pyramid-tm
|
37
|
+
Requires-Dist: requests (>=2.32.0)
|
30
38
|
Requires-Dist: sqlalchemy
|
31
39
|
Requires-Dist: translationstring
|
40
|
+
Requires-Dist: urllib3 (>=1.26.17)
|
32
41
|
Requires-Dist: zope.event
|
33
42
|
|
34
43
|
# c2cgeoportal admin interface
|
@@ -42,6 +51,6 @@ make preparedev
|
|
42
51
|
make serve
|
43
52
|
```
|
44
53
|
|
45
|
-
Now open http://localhost:8888/ in your favorite browser.
|
54
|
+
Now open http://localhost:8888/admin/ in your favorite browser.
|
46
55
|
|
47
56
|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
c2cgeoportal_admin/__init__.py,sha256=uuW2AC81qIXn7bH7MLHzf9fhEK4liGg3Zi-TosyzKNs,5478
|
2
|
+
c2cgeoportal_admin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
c2cgeoportal_admin/routes.py,sha256=tgLP5uKhgX80a2gLCpu6C92UtmqwVkOkmJ-tPxEP3QE,4712
|
4
|
+
c2cgeoportal_admin/subscribers.py,sha256=P1CaccDTpuxrWak_gMN2qBurz3OrAZ6aZ1LA7P3avu8,2430
|
5
|
+
c2cgeoportal_admin/widgets.py,sha256=bjMlC4mqx_bAjzIzzu-zqdQ7bc6tVo7mKOMbpmbeN38,6108
|
6
|
+
c2cgeoportal_admin/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
c2cgeoportal_admin/lib/lingua_extractor.py,sha256=Dw4vo46TcUnJ7vvxgFezPYidfEdL2pHJUM0qxAaJ1KE,3380
|
8
|
+
c2cgeoportal_admin/lib/ogcserver_synchronizer.py,sha256=Px9SzBAv5qDTtF1xu6IRzr1u77TA8eAC3cjgI0Rxgks,15515
|
9
|
+
c2cgeoportal_admin/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
+
c2cgeoportal_admin/schemas/dimensions.py,sha256=rPMEuIdGiVGS5e0xqXUu-COVKlrWg9rpp-xe-8aHbOQ,2290
|
11
|
+
c2cgeoportal_admin/schemas/functionalities.py,sha256=AptqKn2oyy74qivzihNfeNvmaDILsl36bSoJdSNXh9Y,3941
|
12
|
+
c2cgeoportal_admin/schemas/interfaces.py,sha256=0NCRDZOqbw7Bwj-l3GNsVwYDHck4F0q1fCSo1kTYoOY,2578
|
13
|
+
c2cgeoportal_admin/schemas/metadata.py,sha256=EOr9hWYBPBJ3iaUmPFgtWnBaNWadX0g9UQ0eeJ6N84E,8991
|
14
|
+
c2cgeoportal_admin/schemas/restriction_areas.py,sha256=48hFUgFznl_1bYsl490YSXLbXfjCY_f6gURQtB_7eIk,2598
|
15
|
+
c2cgeoportal_admin/schemas/roles.py,sha256=4JJrgZNKsj_wru_YGOWxZTEXGVm0hahbAkYf2aePGzI,2507
|
16
|
+
c2cgeoportal_admin/schemas/treegroup.py,sha256=8_aDM5xhtT7m-amaccEgH8T5O-SoRtFYIcGZ01VwHr0,7036
|
17
|
+
c2cgeoportal_admin/schemas/treeitem.py,sha256=qnjrLd2LD7NCBjXqzw7aRn83cw_hYZbepJdLzOz0rBk,2117
|
18
|
+
c2cgeoportal_admin/static/layertree.css,sha256=tk54KGW0yRRmdrY35gOCZG3qTsqWtGNEwvBYPQKhaVs,3177
|
19
|
+
c2cgeoportal_admin/static/navbar.css,sha256=QIaAQsb4n17OfwdKEQdmNDVPCP23Yu-oGW4xsSaHyW0,2307
|
20
|
+
c2cgeoportal_admin/static/theme.css,sha256=eHtBEJcBtDhyZJvCKNxE5hgril0VpLtcDKfNFdgCSVw,2025
|
21
|
+
c2cgeoportal_admin/templates/404.jinja2,sha256=KSpqCNFwv37rKSmX6kL_VvCnn5egcT1eRD6kIKwWx34,1807
|
22
|
+
c2cgeoportal_admin/templates/edit.jinja2,sha256=rkBQiz0JZdL7VDq8XrhRLTv6JaiFt_QB8CwP3NMHWQY,1302
|
23
|
+
c2cgeoportal_admin/templates/home.jinja2,sha256=WDQwmBGMZxsiOLw9YeYPLuca_mjjntjrTh529euzd1o,1516
|
24
|
+
c2cgeoportal_admin/templates/index.jinja2,sha256=HPgilbqh5dv-yc_T_bc1hV2DEtV2wD617_aAERC2VSk,2005
|
25
|
+
c2cgeoportal_admin/templates/layertree.jinja2,sha256=1ys5XDY3nb4gAu8JazkwSFeJUdGRadT7WaBuvin_hYg,9830
|
26
|
+
c2cgeoportal_admin/templates/layout.jinja2,sha256=KCDwATUYBu-ZXv7ijo0S0PlTmKtU-JxW8gMhvPA_kAE,4105
|
27
|
+
c2cgeoportal_admin/templates/navigation_navbar.jinja2,sha256=XzVQDpo3ClIiRxWf5eDULHZi9u-veYOmndiE_Twqxog,4166
|
28
|
+
c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2,sha256=rdQfbHBzrV5VUq5TC97QR7pv8bRvrdKaUUZpnQyldoE,4327
|
29
|
+
c2cgeoportal_admin/templates/widgets/child.pt,sha256=JjxI0oVADhS3SoFgg0iN8P4ca1I_UGr7fWRp3wpZXsE,2159
|
30
|
+
c2cgeoportal_admin/templates/widgets/children.pt,sha256=0TPpatvmZcU2TxbcZMjDz8VQcLGtoHkuDJ-eAGvjXho,6625
|
31
|
+
c2cgeoportal_admin/templates/widgets/dimension.pt,sha256=1BXmE7s9JpzaJSHAQEtZk0DHB11pQ4FNQPaG_4c8CYo,2627
|
32
|
+
c2cgeoportal_admin/templates/widgets/dimensions.pt,sha256=LjWjsgdcFYZxpB_30-3NOfvq5KYkKTu49F-P-r9d5Jg,1211
|
33
|
+
c2cgeoportal_admin/templates/widgets/functionality_fields.pt,sha256=8TvwXCmQOtYFkiqsa4AHFUYsWk92LLnthz8bDrLmMBc,1969
|
34
|
+
c2cgeoportal_admin/templates/widgets/layer_fields.pt,sha256=RJBYt8ji6YQp9ZaNZJD-caLgy856a6rzlKSMnuZWphw,3223
|
35
|
+
c2cgeoportal_admin/templates/widgets/layer_group_fields.pt,sha256=xnqIqFjPPan81OqLwKeDnvNtlhEvYss6h2J9txH5neE,2459
|
36
|
+
c2cgeoportal_admin/templates/widgets/layer_v1_fields.pt,sha256=w-MujUevHWmnOkOTbbvES6alDoL_UO1eiMj8SCxcQEY,3956
|
37
|
+
c2cgeoportal_admin/templates/widgets/metadata.pt,sha256=P8noHX8YAv3m6EGh0IDUJCFsyeZDX88HtlqOWab8DAU,3735
|
38
|
+
c2cgeoportal_admin/templates/widgets/metadatas.pt,sha256=ErgAH0DA94MO7gqEJ2iZdQ9LRptP2YKH78yze-jdl2Q,1476
|
39
|
+
c2cgeoportal_admin/templates/widgets/ogcserver_fields.pt,sha256=x0bDmgrnj9SA6RCVpg3k2lTkkXPkuBFPKMScDgDeyGU,1724
|
40
|
+
c2cgeoportal_admin/templates/widgets/restriction_area_fields.pt,sha256=pZVE0KcitAF7HXc3ZlniLr0QwSD05TOhlgieLUR1i7Q,1731
|
41
|
+
c2cgeoportal_admin/templates/widgets/role_fields.pt,sha256=gVd9eRYaqw8fGmZauqEUS_Igmyxaa71qcmdC1KUx5nY,2623
|
42
|
+
c2cgeoportal_admin/templates/widgets/theme_fields.pt,sha256=68G1Ya8-Dc6pCeP-taQ0ofCIpnY_v0rouazkFhfQflU,3083
|
43
|
+
c2cgeoportal_admin/templates/widgets/user_fields.pt,sha256=twmajhUYL1xa47Eu-iATKifNPA5lu3SGpqdKajH6gL8,1753
|
44
|
+
c2cgeoportal_admin/views/__init__.py,sha256=jtI6CdoXJwizznjwb8ClYySgq4kbwhTIJYutSw89PAw,683
|
45
|
+
c2cgeoportal_admin/views/dimension_layers.py,sha256=jupwqX_kO37ukcWE-SsO290JdKENEmfoYxk4sRWb25Y,2598
|
46
|
+
c2cgeoportal_admin/views/functionalities.py,sha256=4oZYgs2_M0Usb3GBi40gCP6XvTbR-1PhCDZXiBnhsuk,4031
|
47
|
+
c2cgeoportal_admin/views/home.py,sha256=h_hJWIKpzJeSmXl58J0nvZdEg7avSYOOVUEEnlV-r0k,1943
|
48
|
+
c2cgeoportal_admin/views/interfaces.py,sha256=gzIRrd4D64iSH7NVaR-9oQh8-iMzjZOW5QfTfpQeYU4,3494
|
49
|
+
c2cgeoportal_admin/views/layer_groups.py,sha256=Zcdr26jyo4ZZw7sr6hYOjo6PuI9-StQ5KQ7OlIxSEtY,3956
|
50
|
+
c2cgeoportal_admin/views/layers.py,sha256=xjvcRvKVpeD-LRuVwE8PGkDT-Kih9ADX0beEDcOP1bE,3039
|
51
|
+
c2cgeoportal_admin/views/layers_vectortiles.py,sha256=lREdMc7bo2TVqdf-s6MzNXZoauReqFS_K-Hng49NUT4,4932
|
52
|
+
c2cgeoportal_admin/views/layers_wms.py,sha256=Kpgr-eWME9zxahkf-re1w6wkToKBqyInmqd_DHhj9Kc,8040
|
53
|
+
c2cgeoportal_admin/views/layers_wmts.py,sha256=HNZalKLLhPF7aXLxuFP07yr9-MGnJTg-CVD-GeokvMM,7815
|
54
|
+
c2cgeoportal_admin/views/layertree.py,sha256=plb5fL9vTaSe9EFp8VmUWl5iD9FuiQ-3TuStKAGjIKo,8587
|
55
|
+
c2cgeoportal_admin/views/logged_views.py,sha256=_XHoIl7Lw3SV_1T0c0JUeIhkluzNnjNrSUgimfk993E,3169
|
56
|
+
c2cgeoportal_admin/views/logs.py,sha256=I4ZnfNtBZmriDLIzLpLiX5HPm3Y1UvIQehemPbC2rL0,3616
|
57
|
+
c2cgeoportal_admin/views/oauth2_clients.py,sha256=lfMSwZW7pybQx3PR1btRY7XFLfx1TOx7ooVgllOqK-s,3798
|
58
|
+
c2cgeoportal_admin/views/ogc_servers.py,sha256=nGTs_pDr2knS_NAakqvxmjZE2ulrWxn2puWA_uNqgaY,9412
|
59
|
+
c2cgeoportal_admin/views/restriction_areas.py,sha256=uzfQQVRFCP-OCg1sdGzQCTkO35C1H8DZNMWIquFQqRw,5578
|
60
|
+
c2cgeoportal_admin/views/roles.py,sha256=VP0OEsW2_l99YnxGO5mdOkvPBs4Hs3nyRSbetIKtx14,5887
|
61
|
+
c2cgeoportal_admin/views/themes.py,sha256=mxpf56KXwCKG5tCYgV7xgPtQqlCU67iOBOLB7cHD-Hc,5710
|
62
|
+
c2cgeoportal_admin/views/themes_ordering.py,sha256=NYN3I2tDwLW5E4G-695DwV0dCbHUAObWVFYZ8Bir1-o,5590
|
63
|
+
c2cgeoportal_admin/views/treeitems.py,sha256=C-vjScmb_HI5QOowx3MGZBJqAHDkGTG90vshPG7FvgA,3889
|
64
|
+
c2cgeoportal_admin/views/users.py,sha256=sXCgVluLLnbbQTG8Q7tmaVfnEcHj5fBiHFCG7owVp1w,5439
|
65
|
+
tests/__init__.py,sha256=oo8kqGfoSh8AV0HhTqQfC0izcIQ8ZQPkNmONSEUUby4,9556
|
66
|
+
tests/conftest.py,sha256=ah7JmR2epDZul2rmMH5wuUzkSpXIjm8dd-cgGjK6_k0,2119
|
67
|
+
tests/test_edit_url.py,sha256=Mo_Vo5xvdpPasfjvhQUif5F3nKVpJ6GQJ_x_Hj5VNY8,4494
|
68
|
+
tests/test_functionalities.py,sha256=tGQbEsQWjr_oExI3vWhLIioxylDaoUaOfEas42YPw50,5191
|
69
|
+
tests/test_home.py,sha256=oWsKaWqRicNpUdaca54YvLIBRaGYnsXlv_Tjqv7guEQ,425
|
70
|
+
tests/test_interface.py,sha256=z1jpRzW0R2e9BJWWurE-j-YkG5yhorn7h1XRIauUQ7A,5669
|
71
|
+
tests/test_layer_groups.py,sha256=bisbaDY0SiyBc0rexYajbcvfdDt8Kux6VqXIEBLSULM,12191
|
72
|
+
tests/test_layers_vectortiles.py,sha256=PpnR8wJyRcsByPTOrrtltQUYzzQ0qRzQM2no1z1rLgU,10404
|
73
|
+
tests/test_layers_wms.py,sha256=ynqO1cnXk2ZbSXR3l9hp0IyG8PMXbmR4eyubnwRvRfU,19494
|
74
|
+
tests/test_layers_wmts.py,sha256=7zye_pZ_e0RyJdoT8oeHKPoYJMKWfTg0K8lEgMIu77Q,12181
|
75
|
+
tests/test_layertree.py,sha256=Dxe10OwuilQ-AEgVIDU4Ns9U6PQ4kPWTxwItdBE7nSg,11335
|
76
|
+
tests/test_learn.py,sha256=gQwe-Bim0eihZH0rbBWDn6_rIBxvQD_lyu9MlOljupM,2307
|
77
|
+
tests/test_left_menu.py,sha256=xnlv5sD0k3wpCChKCnbpYRN0TA895pg8k6wVvjf99-4,919
|
78
|
+
tests/test_lingua_extractor_config.py,sha256=vAfunJ4tVuqTJg4xinPwlB0EvA4sYhjY_iDBfMq8EW4,2495
|
79
|
+
tests/test_logs.py,sha256=sUBC61rCSIfg9HBavhT6c0QPmPYUnEfDm91bUaUF4Q8,3147
|
80
|
+
tests/test_main.py,sha256=_gUdMrMMAEzvGIf1QwkoHQkd0eBACz05ycTidCHP5Ao,365
|
81
|
+
tests/test_metadatas.py,sha256=bVNxvZRKNRMmjQGr7Al1d4H85EjEaoesRpxytyld4Fw,12088
|
82
|
+
tests/test_oauth2_clients.py,sha256=-aowsa2Dw77lxzuBb9ULW4iEJSB9yut-eYGP7YptT0M,7000
|
83
|
+
tests/test_ogc_servers.py,sha256=DGSMVIzYnw3bJT53VFGuPYIPMPCyHJDb5ZPJj1VM3Bo,8204
|
84
|
+
tests/test_restriction_areas.py,sha256=5VhO9ZvtFQPy1kVFm96Mh_vf1LCI5oeIdl0dfvS6JD8,9003
|
85
|
+
tests/test_role.py,sha256=eD7dXwP7RjCg14T9ncTfJuMUU4caY9yW3l5ka-gtCd4,12776
|
86
|
+
tests/test_themes.py,sha256=uhzHe2TbuNoLnL4VdYATPnOqtnZWWPKsvUTq6GUxwiU,16207
|
87
|
+
tests/test_themes_ordering.py,sha256=T4Esr0C3EN5UdeEyYLa4ePvEn-bx3RNPkGBK3lDFoBo,2243
|
88
|
+
tests/test_treegroup.py,sha256=Plv119G4TWlurWLE7Z1mWGeHHPScK_fWKcDmDzMUlIU,576
|
89
|
+
tests/test_user.py,sha256=xD0yoJa_babVK69hHQzDkTs6wRWBMXFGD8k0-DfOd-4,12814
|
90
|
+
tests/themes_ordering.py,sha256=UdydcRIzWC6RRnTMfl2JM_250DHuAhGC7rijHqfy7lk,1342
|
91
|
+
c2cgeoportal_admin-2.8.1.180.dist-info/METADATA,sha256=4IZ5Bu5mH3ErjEWDbuTwu1xItrt3UDnOtbtmZXLYQxQ,1597
|
92
|
+
c2cgeoportal_admin-2.8.1.180.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
93
|
+
c2cgeoportal_admin-2.8.1.180.dist-info/entry_points.txt,sha256=kz-7AnYsbtK04jTpGUtcOeu2NbQiXW3CQV3AjyC32tw,165
|
94
|
+
c2cgeoportal_admin-2.8.1.180.dist-info/top_level.txt,sha256=DgcTJgTvpJUB8HqwYB14PdLBPAOAFk0B8oqnSTFoAU4,25
|
95
|
+
c2cgeoportal_admin-2.8.1.180.dist-info/RECORD,,
|
tests/__init__.py
CHANGED
@@ -38,7 +38,7 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
|
|
38
38
|
RestrictionArea,
|
39
39
|
)
|
40
40
|
|
41
|
-
restrictionareas = [RestrictionArea(name="restrictionarea_{}"
|
41
|
+
restrictionareas = [RestrictionArea(name=f"restrictionarea_{i}") for i in range(0, 5)]
|
42
42
|
|
43
43
|
interfaces = [Interface(name) for name in ["desktop", "mobile", "edit", "routing"]]
|
44
44
|
|
@@ -50,11 +50,10 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
|
|
50
50
|
("snappingConfig", '{"tolerance": 50}'),
|
51
51
|
]
|
52
52
|
|
53
|
-
groups = [LayerGroup(name="layer_group_{}"
|
53
|
+
groups = [LayerGroup(name=f"layer_group_{i}") for i in range(0, 5)]
|
54
54
|
|
55
55
|
layers = []
|
56
56
|
for i in range(0, 25):
|
57
|
-
|
58
57
|
layer = layer_builder(i)
|
59
58
|
|
60
59
|
if add_dimension:
|
@@ -90,23 +89,22 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
|
|
90
89
|
|
91
90
|
|
92
91
|
class AbstractViewsTests:
|
93
|
-
|
94
92
|
_prefix = None # url prefix (index view url). Example: /users
|
95
93
|
|
96
94
|
def get(self, test_app, path="", locale="en", status=200, **kwargs):
|
97
95
|
return test_app.get(
|
98
|
-
"{}{}"
|
99
|
-
headers={"Cookie": "_LOCALE_={}"
|
96
|
+
f"{self._prefix}{path}",
|
97
|
+
headers={"Cookie": f"_LOCALE_={locale}"},
|
100
98
|
status=status,
|
101
99
|
**kwargs,
|
102
100
|
)
|
103
101
|
|
104
102
|
def get_item(self, test_app, item_id, **kwargs):
|
105
|
-
return self.get(test_app, "/{}"
|
103
|
+
return self.get(test_app, f"/{item_id}", **kwargs)
|
106
104
|
|
107
105
|
def check_left_menu(self, resp, title):
|
108
106
|
link = resp.html.select_one(".navbar li.active a")
|
109
|
-
assert "http://localhost{
|
107
|
+
assert f"http://localhost{self._prefix}" == link.attrs["href"]
|
110
108
|
assert title == link.getText()
|
111
109
|
|
112
110
|
def check_grid_headers(self, resp, expected_col_headers, new="New"):
|
@@ -120,11 +118,12 @@ class AbstractViewsTests:
|
|
120
118
|
)
|
121
119
|
actions = resp.html.select_one('th[data-field="actions"]')
|
122
120
|
assert "false" == actions.attrs["data-sortable"]
|
123
|
-
|
121
|
+
if new is not False:
|
122
|
+
assert 1 == len(list(filter(lambda x: next(x.stripped_strings) == new, resp.html.findAll("a"))))
|
124
123
|
|
125
124
|
def check_search(self, test_app, search="", offset=0, limit=10, sort="", order="", total=None):
|
126
125
|
json = test_app.post(
|
127
|
-
"{}/grid.json"
|
126
|
+
f"{self._prefix}/grid.json",
|
128
127
|
params={"offset": offset, "limit": limit, "search": search, "sort": sort, "order": order},
|
129
128
|
status=200,
|
130
129
|
).json
|
@@ -135,8 +134,8 @@ class AbstractViewsTests:
|
|
135
134
|
def check_checkboxes(self, form, name, expected):
|
136
135
|
for i, exp in enumerate(expected):
|
137
136
|
field = form.get(name, index=i)
|
138
|
-
checkbox = form.html.select_one("#{
|
139
|
-
label = form.html.select_one("label[for={}]"
|
137
|
+
checkbox = form.html.select_one(f"#{field.id}")
|
138
|
+
label = form.html.select_one(f"label[for={field.id}]")
|
140
139
|
assert exp["label"] == list(label.stripped_strings)[0]
|
141
140
|
assert exp["value"] == checkbox["value"]
|
142
141
|
assert exp["checked"] == field.checked
|
tests/conftest.py
CHANGED
@@ -56,6 +56,7 @@ def app(app_env, dbsession):
|
|
56
56
|
config.add_request_method(lambda request: dbsession, "dbsession", reify=True)
|
57
57
|
config.add_route("user_add", "user_add")
|
58
58
|
config.add_route("users_nb", "users_nb")
|
59
|
+
config.add_route("base", "/", static=True)
|
59
60
|
config.scan(package="tests")
|
60
61
|
app = config.make_wsgi_app()
|
61
62
|
yield app
|
@@ -67,7 +68,7 @@ def settings(app_env):
|
|
67
68
|
yield app_env.get("registry").settings
|
68
69
|
|
69
70
|
|
70
|
-
@pytest.fixture(scope="session") # noqa: F811
|
71
|
+
@pytest.fixture(scope="session") # noqa: ignore=F811
|
71
72
|
@pytest.mark.usefixtures("app")
|
72
73
|
def test_app(request, app):
|
73
74
|
testapp = WebTestApp(app)
|
tests/test_edit_url.py
CHANGED
@@ -24,12 +24,12 @@ def edit_url_test_data(dbsession, transact):
|
|
24
24
|
Theme,
|
25
25
|
)
|
26
26
|
|
27
|
-
restrictionareas = [RestrictionArea(name="restrictionarea_{}"
|
27
|
+
restrictionareas = [RestrictionArea(name=f"restrictionarea_{i}") for i in range(0, 5)]
|
28
28
|
functionalities = {}
|
29
|
-
for name in ("default_basemap", "
|
29
|
+
for name in ("default_basemap", "default_theme"):
|
30
30
|
functionalities[name] = []
|
31
31
|
for v in range(0, 4):
|
32
|
-
functionality = Functionality(name=name, value="value_{}"
|
32
|
+
functionality = Functionality(name=name, value=f"value_{v}")
|
33
33
|
dbsession.add(functionality)
|
34
34
|
functionalities[name].append(functionality)
|
35
35
|
|
@@ -38,10 +38,10 @@ def edit_url_test_data(dbsession, transact):
|
|
38
38
|
|
39
39
|
layers_wmts = []
|
40
40
|
for i in range(0, 5):
|
41
|
-
name = "layer_wmts_{}"
|
41
|
+
name = f"layer_wmts_{i}"
|
42
42
|
layer_wmts = LayerWMTS(name=name)
|
43
43
|
layer_wmts.layer = name
|
44
|
-
layer_wmts.url = "https://server{}.net/wmts"
|
44
|
+
layer_wmts.url = f"https://server{i}.net/wmts"
|
45
45
|
layer_wmts.restrictionareas = [restrictionareas[i % 5], restrictionareas[(i + 2) % 5]]
|
46
46
|
if i % 10 != 1:
|
47
47
|
layer_wmts.interfaces = [interfaces[i % 4], interfaces[(i + 2) % 4]]
|
@@ -52,8 +52,8 @@ def edit_url_test_data(dbsession, transact):
|
|
52
52
|
|
53
53
|
layers_wms = []
|
54
54
|
for i in range(0, 5):
|
55
|
-
layer_wms = LayerWMS(name="layer_wms_{}"
|
56
|
-
layer_wms.layer = "wms_layer_{}"
|
55
|
+
layer_wms = LayerWMS(name=f"layer_wms_{i}")
|
56
|
+
layer_wms.layer = f"wms_layer_{i}"
|
57
57
|
layer_wms.ogc_server = ogc_server
|
58
58
|
layers_wms.append(layer_wms)
|
59
59
|
dbsession.add(layer_wms)
|
@@ -63,9 +63,7 @@ def edit_url_test_data(dbsession, transact):
|
|
63
63
|
for i in range(0, 5):
|
64
64
|
role = Role("secretary_" + str(i))
|
65
65
|
role.functionalities = [
|
66
|
-
functionalities["
|
67
|
-
functionalities["location"][0],
|
68
|
-
functionalities["location"][1],
|
66
|
+
functionalities["default_theme"][0],
|
69
67
|
]
|
70
68
|
role.restrictionareas = [restrictionareas[0], restrictionareas[1]]
|
71
69
|
dbsession.add(role)
|
@@ -94,16 +92,15 @@ def edit_url_test_data(dbsession, transact):
|
|
94
92
|
|
95
93
|
@pytest.mark.usefixtures("edit_url_test_data", "test_app")
|
96
94
|
class TestUrlEdit(AbstractViewsTests):
|
97
|
-
|
98
95
|
_prefix = "/admin/"
|
99
96
|
|
100
97
|
def _get(self, test_app, tablename, pk):
|
101
|
-
path = "/{}/{}"
|
98
|
+
path = f"/{tablename}/{pk}"
|
102
99
|
return test_app.get(path, status=200)
|
103
100
|
|
104
101
|
def _check_link(self, test_app, resp, item, table, status):
|
105
|
-
link = resp.html.select_one(".form-group.item-{} a"
|
106
|
-
assert re.match(
|
102
|
+
link = resp.html.select_one(f".form-group.item-{item} a")
|
103
|
+
assert re.match(rf"http://localhost/admin/{table}/\d+", link["href"]) is not None
|
107
104
|
test_app.get(link.get("href"), status=status)
|
108
105
|
|
109
106
|
def test_layer_wms_edit(self, edit_url_test_data, test_app):
|