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.
Files changed (78) hide show
  1. c2cgeoportal_admin/__init__.py +32 -10
  2. c2cgeoportal_admin/lib/lingua_extractor.py +77 -0
  3. c2cgeoportal_admin/lib/ogcserver_synchronizer.py +168 -56
  4. c2cgeoportal_admin/py.typed +0 -0
  5. c2cgeoportal_admin/routes.py +7 -4
  6. c2cgeoportal_admin/schemas/dimensions.py +12 -10
  7. c2cgeoportal_admin/schemas/functionalities.py +62 -21
  8. c2cgeoportal_admin/schemas/interfaces.py +22 -18
  9. c2cgeoportal_admin/schemas/metadata.py +100 -47
  10. c2cgeoportal_admin/schemas/restriction_areas.py +21 -19
  11. c2cgeoportal_admin/schemas/roles.py +7 -5
  12. c2cgeoportal_admin/schemas/treegroup.py +38 -17
  13. c2cgeoportal_admin/schemas/treeitem.py +2 -3
  14. c2cgeoportal_admin/static/layertree.css +3 -4
  15. c2cgeoportal_admin/static/navbar.css +36 -35
  16. c2cgeoportal_admin/static/theme.css +16 -9
  17. c2cgeoportal_admin/subscribers.py +3 -3
  18. c2cgeoportal_admin/templates/404.jinja2 +18 -2
  19. c2cgeoportal_admin/templates/layertree.jinja2 +31 -9
  20. c2cgeoportal_admin/templates/navigation_navbar.jinja2 +33 -0
  21. c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +12 -0
  22. c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
  23. c2cgeoportal_admin/templates/widgets/metadata.pt +7 -1
  24. c2cgeoportal_admin/views/__init__.py +29 -0
  25. c2cgeoportal_admin/views/dimension_layers.py +7 -6
  26. c2cgeoportal_admin/views/functionalities.py +33 -6
  27. c2cgeoportal_admin/views/home.py +5 -5
  28. c2cgeoportal_admin/views/interfaces.py +7 -8
  29. c2cgeoportal_admin/views/layer_groups.py +9 -11
  30. c2cgeoportal_admin/views/layers.py +8 -7
  31. c2cgeoportal_admin/views/layers_vectortiles.py +30 -10
  32. c2cgeoportal_admin/views/layers_wms.py +41 -35
  33. c2cgeoportal_admin/views/layers_wmts.py +41 -35
  34. c2cgeoportal_admin/views/layertree.py +36 -28
  35. c2cgeoportal_admin/views/logged_views.py +80 -0
  36. c2cgeoportal_admin/views/logs.py +90 -0
  37. c2cgeoportal_admin/views/oauth2_clients.py +30 -22
  38. c2cgeoportal_admin/views/ogc_servers.py +119 -37
  39. c2cgeoportal_admin/views/restriction_areas.py +13 -11
  40. c2cgeoportal_admin/views/roles.py +16 -12
  41. c2cgeoportal_admin/views/themes.py +15 -14
  42. c2cgeoportal_admin/views/themes_ordering.py +13 -8
  43. c2cgeoportal_admin/views/treeitems.py +14 -12
  44. c2cgeoportal_admin/views/users.py +12 -7
  45. c2cgeoportal_admin/widgets.py +17 -14
  46. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/METADATA +17 -8
  47. c2cgeoportal_admin-2.8.1.180.dist-info/RECORD +95 -0
  48. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.8.1.180.dist-info}/WHEEL +1 -1
  49. c2cgeoportal_admin-2.8.1.180.dist-info/entry_points.txt +6 -0
  50. tests/__init__.py +11 -12
  51. tests/conftest.py +2 -1
  52. tests/test_edit_url.py +11 -14
  53. tests/test_functionalities.py +52 -14
  54. tests/test_home.py +0 -1
  55. tests/test_interface.py +34 -11
  56. tests/test_layer_groups.py +57 -27
  57. tests/test_layers_vectortiles.py +43 -20
  58. tests/test_layers_wms.py +67 -45
  59. tests/test_layers_wmts.py +47 -26
  60. tests/test_layertree.py +99 -16
  61. tests/test_left_menu.py +0 -1
  62. tests/test_lingua_extractor_config.py +64 -0
  63. tests/test_logs.py +103 -0
  64. tests/test_main.py +3 -1
  65. tests/test_metadatas.py +34 -21
  66. tests/test_oauth2_clients.py +37 -9
  67. tests/test_ogc_servers.py +84 -35
  68. tests/test_restriction_areas.py +38 -15
  69. tests/test_role.py +68 -41
  70. tests/test_themes.py +71 -37
  71. tests/test_themes_ordering.py +1 -2
  72. tests/test_treegroup.py +2 -2
  73. tests/test_user.py +48 -17
  74. tests/themes_ordering.py +1 -2
  75. c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -33
  76. c2cgeoportal_admin-2.6.0.dist-info/RECORD +0 -89
  77. c2cgeoportal_admin-2.6.0.dist-info/entry_points.txt +0 -3
  78. {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
- # -*- coding: utf-8 -*-
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-{}".format(item.item_type), "group": "All"}
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-{}".format(item.item_type),
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
- # -*- coding: utf-8 -*-
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
- from c2cgeoform.views.abstract_views import AbstractViews, ListField
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(AbstractViews):
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 layers_group: ", ".join(
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
- has_to_be_registred_in_parent = (
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 has_to_be_registred_in_parent:
79
- parent = self._request.dbsession.query(TreeGroup).get(has_to_be_registred_in_parent)
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(self, query): # pylint: disable=arguments-differ
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
- # -*- coding: utf-8 -*-
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 AbstractViews, ListField
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("roles"))
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(AbstractViews):
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
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
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`` to be used in conjunction with ChildrenWidget,
61
- to manage n-m relationships.
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
- <http://deform.readthedocs.org/en/latest/api.html>
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=no-self-use,useless-return
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(self, request, child) -> Optional[str]: # pylint: disable=no-self-use,useless-return
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``, to be used in conjunction with ChildWidget,
113
- to manage n-m relationships.
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
- <http://deform.readthedocs.org/en/latest/api.html>
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.6.0
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: Programming Language :: Python
12
- Classifier: Programming Language :: Python :: 3
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: Topic :: Internet :: WWW/HTTP
16
- Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
14
+ Classifier: Intended Audience :: Other Audience
17
15
  Classifier: License :: OSI Approved :: BSD License
18
- Classifier: Development Status :: 6 - Mature
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.34.2)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,6 @@
1
+ [lingua.extractors]
2
+ geomapfish-admin-config = c2cgeoportal_admin.lib.lingua_extractor:GeomapfishConfigExtractor
3
+
4
+ [paste.app_factory]
5
+ main = c2cgeoportal_admin:main
6
+
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_{}".format(i)) for i in range(0, 5)]
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_{}".format(i)) for i in range(0, 5)]
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
- "{}{}".format(self._prefix, path),
99
- headers={"Cookie": "_LOCALE_={}".format(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, "/{}".format(item_id), **kwargs)
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{}".format(self._prefix) == link.attrs["href"]
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
- assert 1 == len(list(filter(lambda x: next(x.stripped_strings) == new, resp.html.findAll("a"))))
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".format(self._prefix),
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("#{}".format(field.id))
139
- label = form.html.select_one("label[for={}]".format(field.id))
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_{}".format(i)) for i in range(0, 5)]
27
+ restrictionareas = [RestrictionArea(name=f"restrictionarea_{i}") for i in range(0, 5)]
28
28
  functionalities = {}
29
- for name in ("default_basemap", "location"):
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_{}".format(v))
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_{}".format(i)
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".format(i)
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_{}".format(i))
56
- layer_wms.layer = "wms_layer_{}".format(i)
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["default_basemap"][0],
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 = "/{}/{}".format(tablename, pk)
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".format(item))
106
- assert re.match(r"http://localhost/admin/{}/\d+".format(table), link["href"]) is not None
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):