c2cgeoportal-admin 2.6.0__py3-none-any.whl → 2.9rc44__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 (80) hide show
  1. c2cgeoportal_admin/__init__.py +42 -12
  2. c2cgeoportal_admin/lib/lingva_extractor.py +77 -0
  3. c2cgeoportal_admin/lib/ogcserver_synchronizer.py +170 -57
  4. c2cgeoportal_admin/py.typed +0 -0
  5. c2cgeoportal_admin/routes.py +18 -6
  6. c2cgeoportal_admin/schemas/dimensions.py +16 -10
  7. c2cgeoportal_admin/schemas/functionalities.py +59 -21
  8. c2cgeoportal_admin/schemas/interfaces.py +26 -18
  9. c2cgeoportal_admin/schemas/metadata.py +101 -48
  10. c2cgeoportal_admin/schemas/restriction_areas.py +25 -19
  11. c2cgeoportal_admin/schemas/roles.py +12 -6
  12. c2cgeoportal_admin/schemas/treegroup.py +46 -21
  13. c2cgeoportal_admin/schemas/treeitem.py +3 -4
  14. c2cgeoportal_admin/static/layertree.css +3 -4
  15. c2cgeoportal_admin/static/navbar.css +36 -35
  16. c2cgeoportal_admin/static/theme.css +19 -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 +14 -9
  26. c2cgeoportal_admin/views/functionalities.py +52 -18
  27. c2cgeoportal_admin/views/home.py +5 -5
  28. c2cgeoportal_admin/views/interfaces.py +26 -20
  29. c2cgeoportal_admin/views/layer_groups.py +36 -25
  30. c2cgeoportal_admin/views/layers.py +17 -13
  31. c2cgeoportal_admin/views/layers_cog.py +135 -0
  32. c2cgeoportal_admin/views/layers_vectortiles.py +62 -27
  33. c2cgeoportal_admin/views/layers_wms.py +55 -34
  34. c2cgeoportal_admin/views/layers_wmts.py +54 -34
  35. c2cgeoportal_admin/views/layertree.py +38 -29
  36. c2cgeoportal_admin/views/logged_views.py +83 -0
  37. c2cgeoportal_admin/views/logs.py +91 -0
  38. c2cgeoportal_admin/views/oauth2_clients.py +30 -18
  39. c2cgeoportal_admin/views/ogc_servers.py +132 -36
  40. c2cgeoportal_admin/views/restriction_areas.py +39 -27
  41. c2cgeoportal_admin/views/roles.py +42 -28
  42. c2cgeoportal_admin/views/themes.py +47 -35
  43. c2cgeoportal_admin/views/themes_ordering.py +19 -14
  44. c2cgeoportal_admin/views/treeitems.py +21 -17
  45. c2cgeoportal_admin/views/users.py +46 -26
  46. c2cgeoportal_admin/widgets.py +17 -14
  47. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/METADATA +12 -12
  48. c2cgeoportal_admin-2.9rc44.dist-info/RECORD +97 -0
  49. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/WHEEL +1 -1
  50. c2cgeoportal_admin-2.9rc44.dist-info/entry_points.txt +5 -0
  51. tests/__init__.py +24 -20
  52. tests/conftest.py +22 -11
  53. tests/test_edit_url.py +11 -14
  54. tests/test_functionalities.py +52 -14
  55. tests/test_home.py +0 -1
  56. tests/test_interface.py +34 -11
  57. tests/test_layer_groups.py +57 -27
  58. tests/test_layers_cog.py +243 -0
  59. tests/test_layers_vectortiles.py +43 -25
  60. tests/test_layers_wms.py +67 -45
  61. tests/test_layers_wmts.py +47 -26
  62. tests/test_layertree.py +99 -16
  63. tests/test_left_menu.py +0 -1
  64. tests/test_lingva_extractor_config.py +64 -0
  65. tests/test_logs.py +102 -0
  66. tests/test_main.py +3 -1
  67. tests/test_metadatas.py +34 -21
  68. tests/test_oauth2_clients.py +40 -11
  69. tests/test_ogc_servers.py +84 -35
  70. tests/test_restriction_areas.py +38 -15
  71. tests/test_role.py +71 -43
  72. tests/test_themes.py +71 -37
  73. tests/test_themes_ordering.py +1 -2
  74. tests/test_treegroup.py +2 -2
  75. tests/test_user.py +56 -19
  76. tests/themes_ordering.py +1 -2
  77. c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -33
  78. c2cgeoportal_admin-2.6.0.dist-info/RECORD +0 -89
  79. c2cgeoportal_admin-2.6.0.dist-info/entry_points.txt +0 -3
  80. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.9rc44.dist-info}/top_level.txt +0 -0
@@ -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
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) -> str | None: # 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
+ ) -> str | None:
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,21 +1,23 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: c2cgeoportal-admin
3
- Version: 2.6.0
3
+ Version: 2.9rc44
4
4
  Summary: c2cgeoportal admin
5
5
  Home-page: https://github.com/camptocamp/c2cgeoportal/
6
6
  Author: Camptocamp
7
7
  Author-email: info@camptocamp.com
8
- License: UNKNOWN
9
8
  Keywords: web gis geoportail c2cgeoportal geocommune pyramid
10
- Platform: UNKNOWN
11
- Classifier: Programming Language :: Python
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.7
9
+ Classifier: Development Status :: 6 - Mature
10
+ Classifier: Environment :: Web Environment
14
11
  Classifier: Framework :: Pyramid
15
- Classifier: Topic :: Internet :: WWW/HTTP
16
- Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
12
+ Classifier: Intended Audience :: Other Audience
17
13
  Classifier: License :: OSI Approved :: BSD License
18
- Classifier: Development Status :: 6 - Mature
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Topic :: Scientific/Engineering :: GIS
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
19
21
  Description-Content-Type: text/markdown
20
22
  Requires-Dist: c2cgeoform
21
23
  Requires-Dist: c2cwsgiutils
@@ -42,6 +44,4 @@ make preparedev
42
44
  make serve
43
45
  ```
44
46
 
45
- Now open http://localhost:8888/ in your favorite browser.
46
-
47
-
47
+ Now open http://localhost:8888/admin/ in your favorite browser.
@@ -0,0 +1,97 @@
1
+ c2cgeoportal_admin/__init__.py,sha256=HVSQ-CwK5aR9URA-NVH7JlYHGU49xT5vARiTkdxpV70,5767
2
+ c2cgeoportal_admin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ c2cgeoportal_admin/routes.py,sha256=oja-Seyn08geema9lKJEVU-bPzuT8RaNBfUORDxEm6w,5302
4
+ c2cgeoportal_admin/subscribers.py,sha256=P1CaccDTpuxrWak_gMN2qBurz3OrAZ6aZ1LA7P3avu8,2430
5
+ c2cgeoportal_admin/widgets.py,sha256=8bozaTGBZKxDIMWbkHU1eD0MmOQ9KMOn21PDLYbQGFs,6092
6
+ c2cgeoportal_admin/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ c2cgeoportal_admin/lib/lingva_extractor.py,sha256=5XsUHeVHnGF6GmD83shaTXasigGXtDXwgnswU0xA410,3355
8
+ c2cgeoportal_admin/lib/ogcserver_synchronizer.py,sha256=AFr0TbI_l7QTf9oNyO6rFEy6Ix096R2V0EFYcw-ArIc,15536
9
+ c2cgeoportal_admin/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ c2cgeoportal_admin/schemas/dimensions.py,sha256=pVEN8VjPjoANWUEIB-aWh6Yli_ybu1ghQcaYC2tSFyI,2368
11
+ c2cgeoportal_admin/schemas/functionalities.py,sha256=JecG1DYagM_Bgd7sMj0clN-4CAuYZEdELwDXlLRLBZs,3852
12
+ c2cgeoportal_admin/schemas/interfaces.py,sha256=N_b1LQ0Ur2i09dprnLLqXrcEq1p7uaKZJhaQpW7mOKc,2662
13
+ c2cgeoportal_admin/schemas/metadata.py,sha256=cp-QJkUf0zH0s6rBgV3uIZuXhHVFG5E8mF4J1ty2c6c,8897
14
+ c2cgeoportal_admin/schemas/restriction_areas.py,sha256=1xVR1SQfBReWVK5eFyGyrvw8tYqY2iOehuXVX3EMdf0,2682
15
+ c2cgeoportal_admin/schemas/roles.py,sha256=YyRaStlu1IJwB5gRHlvS285twSy2xxatNOqV9klq1s8,2591
16
+ c2cgeoportal_admin/schemas/treegroup.py,sha256=pLBIGBeaCmsAUMC4yCFCdSkYqLytG38qVygYqNr_AX8,7150
17
+ c2cgeoportal_admin/schemas/treeitem.py,sha256=VhGhpG8VcsT-3dnnNlln-uVlsqjwJQXbg6Ap1tEanMI,2146
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=3knC4gpPnEwLF0-jEJze15C1hm1K87aCpxGyqdjrLxw,2068
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=WL3CqfAY8mref9cen1lCF5vADg_csf2Pp5zeEYX1ZXg,2778
46
+ c2cgeoportal_admin/views/functionalities.py,sha256=F51rdqVqbdWx1iNz8DHauhh3B8f6x6lEidaskxBn1so,4379
47
+ c2cgeoportal_admin/views/home.py,sha256=h_hJWIKpzJeSmXl58J0nvZdEg7avSYOOVUEEnlV-r0k,1943
48
+ c2cgeoportal_admin/views/interfaces.py,sha256=psp5dw22rI3enY9AS0aIspHBdv-sVzSPBQKGIhW3-Hw,3844
49
+ c2cgeoportal_admin/views/layer_groups.py,sha256=xQiEkO7LuNy0FiwfHZa1XwaoMvr9UE2bLpckOtdyuMM,4489
50
+ c2cgeoportal_admin/views/layers.py,sha256=JDEO8hEIPhRxZVpxyT_0FU6gWCgREllw5O9qBCCxipU,3248
51
+ c2cgeoportal_admin/views/layers_cog.py,sha256=tFljZufefGP8YZvidAhUA5cgwbO1R2D7wXdQdS1EX1I,5627
52
+ c2cgeoportal_admin/views/layers_vectortiles.py,sha256=fTNaGGt7ZIX9wydZvED6mp1B8iBtt-qbywv2MqQgV_Q,5617
53
+ c2cgeoportal_admin/views/layers_wms.py,sha256=kjhH4TWnVnH81J__vcbyST2qEMSz3qHOxcEL8ELvLuU,8335
54
+ c2cgeoportal_admin/views/layers_wmts.py,sha256=Kb-j_yPEJycBYh5E-D-eP3xEhuzraotNL9bLup7GoNM,8080
55
+ c2cgeoportal_admin/views/layertree.py,sha256=0FxaVrIg2A7ArMCiI9tj7diaLPn2Cl16iFUerdPDpV4,8629
56
+ c2cgeoportal_admin/views/logged_views.py,sha256=Yg8HnrLCog4geNWOjkhF_Zo2ByOKuevdVT8xLd9x5Ow,3335
57
+ c2cgeoportal_admin/views/logs.py,sha256=N1I0gqzoqbEtkOsP0EhrlEWsDYuiuKQ46_YeKy7zFHs,3776
58
+ c2cgeoportal_admin/views/oauth2_clients.py,sha256=RC_vrMQaYGujN97wHihQXrO_0K7CrcFF1rSI0-dHZlg,3840
59
+ c2cgeoportal_admin/views/ogc_servers.py,sha256=kIhlZ7Sp_mdZUlyl2h4foTTgkevWrbZb_chLZUXEF1o,9716
60
+ c2cgeoportal_admin/views/restriction_areas.py,sha256=QQKDC7nUkNecC2knnnoLijhc2LvvjV8wZm3fcmRjftc,6122
61
+ c2cgeoportal_admin/views/roles.py,sha256=I6di90WR20EkFoy33milrHZ74_dgCkEVeNDM8E4P46w,6387
62
+ c2cgeoportal_admin/views/themes.py,sha256=6le9_3vhYa_ez0q52i--M24xPsycrGtpVKoCRhn7H0k,6267
63
+ c2cgeoportal_admin/views/themes_ordering.py,sha256=PgPaqKe7A5d2cYcDeJyoK615BNXayOmRcKNAAopvfRc,5689
64
+ c2cgeoportal_admin/views/treeitems.py,sha256=EgDArC5M39iihbB1Ok2VXmAAuH2DhhBrjeF0TbJgOQ4,4038
65
+ c2cgeoportal_admin/views/users.py,sha256=8zoSgSn0RFnu-Gc6gJr58T5ySsd0L2UQFZdSwfptdY8,6147
66
+ tests/__init__.py,sha256=weLUoRCG6zIlhW7Rfr7QEA0Ju-gYLfBekRcTCb5lTZ4,9785
67
+ tests/conftest.py,sha256=vowo5nwQ3DLSfost3ndihoYJFuhuhpoK__-B_ffsSLY,2646
68
+ tests/test_edit_url.py,sha256=Mo_Vo5xvdpPasfjvhQUif5F3nKVpJ6GQJ_x_Hj5VNY8,4494
69
+ tests/test_functionalities.py,sha256=tGQbEsQWjr_oExI3vWhLIioxylDaoUaOfEas42YPw50,5191
70
+ tests/test_home.py,sha256=oWsKaWqRicNpUdaca54YvLIBRaGYnsXlv_Tjqv7guEQ,425
71
+ tests/test_interface.py,sha256=z1jpRzW0R2e9BJWWurE-j-YkG5yhorn7h1XRIauUQ7A,5669
72
+ tests/test_layer_groups.py,sha256=bisbaDY0SiyBc0rexYajbcvfdDt8Kux6VqXIEBLSULM,12191
73
+ tests/test_layers_cog.py,sha256=5p7NHZw1IXfHg8Weqie3ibjDIJYVm7KAGGOiaZoBYO0,9848
74
+ tests/test_layers_vectortiles.py,sha256=uZGO-0-uVuvkPVMQI11tSY381tEmgWeYvlxKI19pslg,10158
75
+ tests/test_layers_wms.py,sha256=ynqO1cnXk2ZbSXR3l9hp0IyG8PMXbmR4eyubnwRvRfU,19494
76
+ tests/test_layers_wmts.py,sha256=7zye_pZ_e0RyJdoT8oeHKPoYJMKWfTg0K8lEgMIu77Q,12181
77
+ tests/test_layertree.py,sha256=Dxe10OwuilQ-AEgVIDU4Ns9U6PQ4kPWTxwItdBE7nSg,11335
78
+ tests/test_learn.py,sha256=gQwe-Bim0eihZH0rbBWDn6_rIBxvQD_lyu9MlOljupM,2307
79
+ tests/test_left_menu.py,sha256=xnlv5sD0k3wpCChKCnbpYRN0TA895pg8k6wVvjf99-4,919
80
+ tests/test_lingva_extractor_config.py,sha256=ZQE8zBl91khK68MX0chL6mQPgfpIWQgMxlqFFpCwmSw,2495
81
+ tests/test_logs.py,sha256=pxzHyOElW-x2-M3yoMEsHIZ3nrm5EptDAAAGfziEfv4,3132
82
+ tests/test_main.py,sha256=_gUdMrMMAEzvGIf1QwkoHQkd0eBACz05ycTidCHP5Ao,365
83
+ tests/test_metadatas.py,sha256=bVNxvZRKNRMmjQGr7Al1d4H85EjEaoesRpxytyld4Fw,12088
84
+ tests/test_oauth2_clients.py,sha256=5vyuCsba2WVgr6yMJysw73pAnXCZXhLO7dLIgV-spic,7028
85
+ tests/test_ogc_servers.py,sha256=DGSMVIzYnw3bJT53VFGuPYIPMPCyHJDb5ZPJj1VM3Bo,8204
86
+ tests/test_restriction_areas.py,sha256=5VhO9ZvtFQPy1kVFm96Mh_vf1LCI5oeIdl0dfvS6JD8,9003
87
+ tests/test_role.py,sha256=2mbi0RwTESnIZIuUTxMi275ONOcPNKWN-ni7b00SO90,12804
88
+ tests/test_themes.py,sha256=uhzHe2TbuNoLnL4VdYATPnOqtnZWWPKsvUTq6GUxwiU,16207
89
+ tests/test_themes_ordering.py,sha256=T4Esr0C3EN5UdeEyYLa4ePvEn-bx3RNPkGBK3lDFoBo,2243
90
+ tests/test_treegroup.py,sha256=Plv119G4TWlurWLE7Z1mWGeHHPScK_fWKcDmDzMUlIU,576
91
+ tests/test_user.py,sha256=5C9nrQVk4Bf0Z9BKd0uf_J8EtJLTOFSpzrNHXfg3NzI,13095
92
+ tests/themes_ordering.py,sha256=UdydcRIzWC6RRnTMfl2JM_250DHuAhGC7rijHqfy7lk,1342
93
+ c2cgeoportal_admin-2.9rc44.dist-info/METADATA,sha256=FL4D_vI8WCcesDbNuwvSy7SVtqGOj7z5mYoC_jQRlQc,1382
94
+ c2cgeoportal_admin-2.9rc44.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
95
+ c2cgeoportal_admin-2.9rc44.dist-info/entry_points.txt,sha256=iRK5w2E-PVbqHx48OuxznFEXTpoOdJyx6kjpaca0Fxc,164
96
+ c2cgeoportal_admin-2.9rc44.dist-info/top_level.txt,sha256=DgcTJgTvpJUB8HqwYB14PdLBPAOAFk0B8oqnSTFoAU4,25
97
+ c2cgeoportal_admin-2.9rc44.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.42.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1,5 @@
1
+ [lingva.extractors]
2
+ geomapfish-admin-config = c2cgeoportal_admin.lib.lingva_extractor:GeomapfishConfigExtractor
3
+
4
+ [paste.app_factory]
5
+ main = c2cgeoportal_admin:main
tests/__init__.py CHANGED
@@ -9,13 +9,15 @@ skip_if_ci = pytest.mark.skipif(os.environ.get("CI", "false") == "true", reason=
9
9
 
10
10
 
11
11
  def get_test_default_layers(dbsession, default_ogc_server):
12
- from c2cgeoportal_commons.models.main import LayerVectorTiles, LayerWMS, LayerWMTS
13
-
14
- default_wms = LayerWMS("wms-defaults")
15
- default_wms.ogc_server = default_ogc_server
16
- default_wms.time_widget = "datepicker"
17
- default_wms.time_mode = "value"
18
- dbsession.add(default_wms)
12
+ from c2cgeoportal_commons.models.main import LayerCOG, LayerVectorTiles, LayerWMS, LayerWMTS
13
+
14
+ default_wms = None
15
+ if default_ogc_server:
16
+ default_wms = LayerWMS("wms-defaults")
17
+ default_wms.ogc_server = default_ogc_server
18
+ default_wms.time_widget = "datepicker"
19
+ default_wms.time_mode = "value"
20
+ dbsession.add(default_wms)
19
21
  default_wmts = LayerWMTS("wmts-defaults")
20
22
  default_wmts.url = "https:///wmts.geo.admin_default.ch.org?service=wms&request=GetCapabilities"
21
23
  default_wmts.layer = "default"
@@ -24,8 +26,11 @@ def get_test_default_layers(dbsession, default_ogc_server):
24
26
  default_vectortiles = LayerVectorTiles("vectortiles-defaults")
25
27
  default_vectortiles.style = "https://vectortiles-staging.geoportail.lu/styles/roadmap/style.json"
26
28
  dbsession.add(default_vectortiles)
29
+ default_cog = LayerCOG("cog-defaults")
30
+ default_cog.url = "https://example.com/image.tiff"
31
+ dbsession.add(default_cog)
27
32
  dbsession.flush()
28
- return {"wms": default_wms, "wmts": default_wmts, "vectortiles": default_vectortiles}
33
+ return {"wms": default_wms, "wmts": default_wmts, "vectortiles": default_vectortiles, "cog": default_cog}
29
34
 
30
35
 
31
36
  def factory_build_layers(layer_builder, dbsession, add_dimension=True):
@@ -38,7 +43,7 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
38
43
  RestrictionArea,
39
44
  )
40
45
 
41
- restrictionareas = [RestrictionArea(name="restrictionarea_{}".format(i)) for i in range(0, 5)]
46
+ restrictionareas = [RestrictionArea(name=f"restrictionarea_{i}") for i in range(0, 5)]
42
47
 
43
48
  interfaces = [Interface(name) for name in ["desktop", "mobile", "edit", "routing"]]
44
49
 
@@ -50,11 +55,10 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
50
55
  ("snappingConfig", '{"tolerance": 50}'),
51
56
  ]
52
57
 
53
- groups = [LayerGroup(name="layer_group_{}".format(i)) for i in range(0, 5)]
58
+ groups = [LayerGroup(name=f"layer_group_{i}") for i in range(0, 5)]
54
59
 
55
60
  layers = []
56
61
  for i in range(0, 25):
57
-
58
62
  layer = layer_builder(i)
59
63
 
60
64
  if add_dimension:
@@ -90,23 +94,22 @@ def factory_build_layers(layer_builder, dbsession, add_dimension=True):
90
94
 
91
95
 
92
96
  class AbstractViewsTests:
93
-
94
97
  _prefix = None # url prefix (index view url). Example: /users
95
98
 
96
99
  def get(self, test_app, path="", locale="en", status=200, **kwargs):
97
100
  return test_app.get(
98
- "{}{}".format(self._prefix, path),
99
- headers={"Cookie": "_LOCALE_={}".format(locale)},
101
+ f"{self._prefix}{path}",
102
+ headers={"Cookie": f"_LOCALE_={locale}"},
100
103
  status=status,
101
104
  **kwargs,
102
105
  )
103
106
 
104
107
  def get_item(self, test_app, item_id, **kwargs):
105
- return self.get(test_app, "/{}".format(item_id), **kwargs)
108
+ return self.get(test_app, f"/{item_id}", **kwargs)
106
109
 
107
110
  def check_left_menu(self, resp, title):
108
111
  link = resp.html.select_one(".navbar li.active a")
109
- assert "http://localhost{}".format(self._prefix) == link.attrs["href"]
112
+ assert f"http://localhost{self._prefix}" == link.attrs["href"]
110
113
  assert title == link.getText()
111
114
 
112
115
  def check_grid_headers(self, resp, expected_col_headers, new="New"):
@@ -120,11 +123,12 @@ class AbstractViewsTests:
120
123
  )
121
124
  actions = resp.html.select_one('th[data-field="actions"]')
122
125
  assert "false" == actions.attrs["data-sortable"]
123
- assert 1 == len(list(filter(lambda x: next(x.stripped_strings) == new, resp.html.findAll("a"))))
126
+ if new is not False:
127
+ assert 1 == len(list(filter(lambda x: next(x.stripped_strings) == new, resp.html.findAll("a"))))
124
128
 
125
129
  def check_search(self, test_app, search="", offset=0, limit=10, sort="", order="", total=None):
126
130
  json = test_app.post(
127
- "{}/grid.json".format(self._prefix),
131
+ f"{self._prefix}/grid.json",
128
132
  params={"offset": offset, "limit": limit, "search": search, "sort": sort, "order": order},
129
133
  status=200,
130
134
  ).json
@@ -135,8 +139,8 @@ class AbstractViewsTests:
135
139
  def check_checkboxes(self, form, name, expected):
136
140
  for i, exp in enumerate(expected):
137
141
  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))
142
+ checkbox = form.html.select_one(f"#{field.id}")
143
+ label = form.html.select_one(f"label[for={field.id}]")
140
144
  assert exp["label"] == list(label.stripped_strings)[0]
141
145
  assert exp["value"] == checkbox["value"]
142
146
  assert exp["checked"] == field.checked
tests/conftest.py CHANGED
@@ -1,8 +1,15 @@
1
+ from typing import Any
2
+
3
+ import pyramid.request
1
4
  import pytest
5
+ import sqlalchemy.exc
2
6
  import transaction
3
7
  from pyramid import testing
4
8
  from pyramid.paster import bootstrap
9
+ from pyramid.router import Router
10
+ from pyramid.scripting import AppEnvironment
5
11
  from sqlalchemy.exc import DBAPIError
12
+ from sqlalchemy.orm import Session, SessionTransaction
6
13
  from webtest import TestApp as WebTestApp # Avoid warning with pytest
7
14
 
8
15
  from c2cgeoportal_commons.testing import generate_mappers, get_engine, get_session_factory, get_tm_session
@@ -11,31 +18,34 @@ from c2cgeoportal_commons.testing.initializedb import truncate_tables
11
18
 
12
19
  @pytest.fixture(scope="session")
13
20
  @pytest.mark.usefixtures("settings")
14
- def dbsession(settings):
21
+ def dbsession(settings: dict[str, Any]) -> Session:
15
22
  generate_mappers()
16
23
  engine = get_engine(settings)
17
- truncate_tables(engine)
18
24
  session_factory = get_session_factory(engine)
19
25
  session = get_tm_session(session_factory, transaction.manager)
26
+ truncate_tables(session)
20
27
  yield session
21
28
 
22
29
 
23
30
  @pytest.fixture(scope="function")
24
31
  @pytest.mark.usefixtures("dbsession")
25
- def transact(dbsession):
32
+ def transact(dbsession: Session) -> SessionTransaction:
26
33
  t = dbsession.begin_nested()
27
34
  yield t
28
- t.rollback()
35
+ try:
36
+ t.rollback()
37
+ except sqlalchemy.exc.ResourceClosedError:
38
+ print("The transaction was already closed")
29
39
  dbsession.expire_all()
30
40
 
31
41
 
32
- def raise_db_error(_):
42
+ def raise_db_error(_: Any) -> None:
33
43
  raise DBAPIError("this is a test !", None, None)
34
44
 
35
45
 
36
46
  @pytest.fixture(scope="function")
37
47
  @pytest.mark.usefixtures("dbsession")
38
- def raise_db_error_on_query(dbsession):
48
+ def raise_db_error_on_query(dbsession: Session) -> None:
39
49
  query = dbsession.query
40
50
  dbsession.query = raise_db_error
41
51
  yield
@@ -43,7 +53,7 @@ def raise_db_error_on_query(dbsession):
43
53
 
44
54
 
45
55
  @pytest.fixture(scope="session")
46
- def app_env():
56
+ def app_env() -> AppEnvironment:
47
57
  file_name = "/opt/c2cgeoportal/admin/tests/tests.ini"
48
58
  with bootstrap(file_name) as env:
49
59
  yield env
@@ -51,11 +61,12 @@ def app_env():
51
61
 
52
62
  @pytest.fixture(scope="session")
53
63
  @pytest.mark.usefixtures("app_env", "dbsession")
54
- def app(app_env, dbsession):
64
+ def app(app_env: AppEnvironment, dbsession: Session) -> Router:
55
65
  config = testing.setUp(registry=app_env["registry"])
56
66
  config.add_request_method(lambda request: dbsession, "dbsession", reify=True)
57
67
  config.add_route("user_add", "user_add")
58
68
  config.add_route("users_nb", "users_nb")
69
+ config.add_route("base", "/", static=True)
59
70
  config.scan(package="tests")
60
71
  app = config.make_wsgi_app()
61
72
  yield app
@@ -63,12 +74,12 @@ def app(app_env, dbsession):
63
74
 
64
75
  @pytest.fixture(scope="session")
65
76
  @pytest.mark.usefixtures("app_env")
66
- def settings(app_env):
77
+ def settings(app_env: AppEnvironment) -> Any:
67
78
  yield app_env.get("registry").settings
68
79
 
69
80
 
70
- @pytest.fixture(scope="session") # noqa: F811
81
+ @pytest.fixture(scope="session") # noqa: ignore=F811
71
82
  @pytest.mark.usefixtures("app")
72
- def test_app(request, app):
83
+ def test_app(request: pyramid.request.Request, app: Router) -> WebTestApp:
73
84
  testapp = WebTestApp(app)
74
85
  yield testapp
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):
@@ -9,15 +9,18 @@ from . import AbstractViewsTests
9
9
 
10
10
  @pytest.fixture(scope="function")
11
11
  @pytest.mark.usefixtures("dbsession", "transact")
12
- def functionality_test_data(dbsession, transact):
12
+ def functionality_test_data(dbsession, transact, settings):
13
13
  del transact
14
14
 
15
15
  from c2cgeoportal_commons.models.main import Functionality
16
16
 
17
17
  functionalities = []
18
18
  for i in range(0, 4):
19
- functionality = Functionality(name="functionality_{}".format(i), value="value_{}".format(i))
20
- functionality.description = "description_{}".format(i)
19
+ functionality = Functionality(
20
+ settings["admin_interface"]["available_functionalities"][i]["name"],
21
+ value=f"value_{i}",
22
+ )
23
+ functionality.description = f"description_{i}"
21
24
  dbsession.add(functionality)
22
25
  functionalities.append(functionality)
23
26
 
@@ -28,7 +31,6 @@ def functionality_test_data(dbsession, transact):
28
31
 
29
32
  @pytest.mark.usefixtures("functionality_test_data", "test_app")
30
33
  class TestFunctionality(AbstractViewsTests):
31
-
32
34
  _prefix = "/admin/functionalities"
33
35
 
34
36
  def test_index_rendering(self, test_app):
@@ -47,10 +49,10 @@ class TestFunctionality(AbstractViewsTests):
47
49
 
48
50
  def test_grid_search(self, test_app):
49
51
  # search on functionality name
50
- self.check_search(test_app, "functionality_0", total=1)
52
+ self.check_search(test_app, "default_basemap", total=1)
51
53
 
52
54
  def test_submit_new(self, dbsession, test_app):
53
- from c2cgeoportal_commons.models.main import Functionality
55
+ from c2cgeoportal_commons.models.main import Functionality, Log, LogAction
54
56
 
55
57
  resp = test_app.post(
56
58
  "/admin/functionalities/new",
@@ -63,9 +65,19 @@ class TestFunctionality(AbstractViewsTests):
63
65
  ).group(1)
64
66
  assert functionality.name == "new_name"
65
67
 
66
- def test_edit(self, test_app, functionality_test_data):
68
+ log = dbsession.query(Log).one()
69
+ assert log.date != None
70
+ assert log.action == LogAction.INSERT
71
+ assert log.element_type == "functionality"
72
+ assert log.element_id == functionality.id
73
+ assert log.element_name == functionality.name
74
+ assert log.username == "test_user"
75
+
76
+ def test_edit(self, test_app, functionality_test_data, dbsession):
77
+ from c2cgeoportal_commons.models.main import Log, LogAction
78
+
67
79
  functionality = functionality_test_data["functionalities"][0]
68
- resp = test_app.get("/admin/functionalities/{}".format(functionality.id), status=200)
80
+ resp = test_app.get(f"/admin/functionalities/{functionality.id}", status=200)
69
81
  form = resp.form
70
82
  assert str(functionality.id) == self.get_first_field_named(form, "id").value
71
83
  assert "hidden" == self.get_first_field_named(form, "id").attrs["type"]
@@ -74,25 +86,51 @@ class TestFunctionality(AbstractViewsTests):
74
86
  assert form.submit().status_int == 302
75
87
  assert functionality.description == "new_description"
76
88
 
89
+ log = dbsession.query(Log).one()
90
+ assert log.date != None
91
+ assert log.action == LogAction.UPDATE
92
+ assert log.element_type == "functionality"
93
+ assert log.element_id == functionality.id
94
+ assert log.element_name == functionality.name
95
+ assert log.username == "test_user"
96
+
77
97
  def test_delete(self, test_app, functionality_test_data, dbsession):
78
- from c2cgeoportal_commons.models.main import Functionality
98
+ from c2cgeoportal_commons.models.main import Functionality, Log, LogAction
79
99
 
80
100
  functionality = functionality_test_data["functionalities"][0]
81
101
  deleted_id = functionality.id
82
- test_app.delete("/admin/functionalities/{}".format(deleted_id), status=200)
102
+ test_app.delete(f"/admin/functionalities/{deleted_id}", status=200)
83
103
  assert dbsession.query(Functionality).get(deleted_id) is None
84
104
 
105
+ log = dbsession.query(Log).one()
106
+ assert log.date != None
107
+ assert log.action == LogAction.DELETE
108
+ assert log.element_type == "functionality"
109
+ assert log.element_id == functionality.id
110
+ assert log.element_name == functionality.name
111
+ assert log.username == "test_user"
112
+
85
113
  def test_duplicate(self, functionality_test_data, test_app, dbsession):
86
114
  from c2cgeoportal_commons.models.main import Functionality
87
115
 
88
116
  functionality = functionality_test_data["functionalities"][3]
89
- resp = test_app.get("/admin/functionalities/{}/duplicate".format(functionality.id), status=200)
117
+
118
+ resp = test_app.get(f"/admin/functionalities/{functionality.id}/duplicate", status=200)
119
+
90
120
  form = resp.form
91
- assert "" == self.get_first_field_named(form, "id").value
92
- self.set_first_field_named(form, "name", "clone")
121
+ assert form["name"].value == functionality.name
122
+ assert form["description"].value == functionality.description
123
+ assert form["value"].value == functionality.value
124
+ form["value"].value = "another_value"
93
125
  resp = form.submit("submit")
126
+
94
127
  assert resp.status_int == 302
95
- functionality = dbsession.query(Functionality).filter(Functionality.name == "clone").one()
128
+ functionality = (
129
+ dbsession.query(Functionality)
130
+ .filter(Functionality.name == functionality.name)
131
+ .filter(Functionality.value == "another_value")
132
+ .one()
133
+ )
96
134
  assert str(functionality.id) == re.match(
97
135
  r"http://localhost/admin/functionalities/(.*)\?msg_col=submit_ok", resp.location
98
136
  ).group(1)
tests/test_home.py CHANGED
@@ -5,7 +5,6 @@ from . import AbstractViewsTests
5
5
 
6
6
  @pytest.mark.usefixtures("test_app")
7
7
  class TestHome(AbstractViewsTests):
8
-
9
8
  _prefix = "/admin/"
10
9
 
11
10
  def test_index_rendering(self, test_app):