c2cgeoportal-geoportal 2.6.0__py2.py3-none-any.whl → 2.8.1.180__py2.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 (225) hide show
  1. c2cgeoportal_geoportal/__init__.py +245 -95
  2. c2cgeoportal_geoportal/lib/__init__.py +67 -43
  3. c2cgeoportal_geoportal/lib/authentication.py +50 -26
  4. c2cgeoportal_geoportal/lib/bashcolor.py +17 -13
  5. c2cgeoportal_geoportal/lib/cacheversion.py +16 -8
  6. c2cgeoportal_geoportal/lib/caching.py +65 -193
  7. c2cgeoportal_geoportal/lib/check_collector.py +17 -10
  8. c2cgeoportal_geoportal/lib/checker.py +67 -65
  9. c2cgeoportal_geoportal/lib/common_headers.py +167 -0
  10. c2cgeoportal_geoportal/lib/dbreflection.py +61 -46
  11. c2cgeoportal_geoportal/lib/filter_capabilities.py +126 -88
  12. c2cgeoportal_geoportal/lib/fulltextsearch.py +6 -5
  13. c2cgeoportal_geoportal/lib/functionality.py +20 -17
  14. c2cgeoportal_geoportal/lib/headers.py +14 -5
  15. c2cgeoportal_geoportal/lib/i18n.py +4 -4
  16. c2cgeoportal_geoportal/lib/layers.py +30 -11
  17. c2cgeoportal_geoportal/lib/lingua_extractor.py +363 -240
  18. c2cgeoportal_geoportal/lib/loader.py +11 -16
  19. c2cgeoportal_geoportal/lib/metrics.py +28 -17
  20. c2cgeoportal_geoportal/lib/oauth2.py +392 -206
  21. c2cgeoportal_geoportal/lib/wmstparsing.py +105 -84
  22. c2cgeoportal_geoportal/lib/xsd.py +26 -16
  23. c2cgeoportal_geoportal/resources.py +15 -9
  24. c2cgeoportal_geoportal/scaffolds/advance_create/ci/config.yaml +26 -0
  25. c2cgeoportal_geoportal/scaffolds/advance_create/cookiecutter.json +18 -0
  26. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.dockerignore +6 -0
  27. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.eslintrc.yaml +19 -0
  28. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+dot+prospector.yaml → advance_create/{{cookiecutter.project}}/geoportal/.prospector.yaml} +8 -2
  29. c2cgeoportal_geoportal/scaffolds/{create/geoportal/Dockerfile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Dockerfile} +22 -15
  30. c2cgeoportal_geoportal/scaffolds/{create/geoportal/alembic.yaml_tmpl → advance_create/{{cookiecutter.project}}/geoportal/alembic.yaml} +1 -1
  31. c2cgeoportal_geoportal/scaffolds/{create/geoportal/development.ini_tmpl → advance_create/{{cookiecutter.project}}/geoportal/development.ini} +34 -15
  32. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +100 -0
  33. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-client.cfg +1 -0
  34. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/production.ini +38 -0
  35. c2cgeoportal_geoportal/scaffolds/{create/geoportal/setup.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/setup.py} +6 -7
  36. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tsconfig.json +8 -0
  37. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +77 -0
  38. c2cgeoportal_geoportal/scaffolds/{create/geoportal/webpack.apps.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js} +29 -28
  39. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.commons.js +4 -7
  40. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.config.js +1 -1
  41. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +42 -0
  42. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/authentication.py +10 -0
  43. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/dev.py +14 -0
  44. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/models.py +8 -0
  45. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/multi_organization.py +7 -0
  46. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/resources.py +4 -3
  47. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/static-ngeo/api/index.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/api/index.js} +1 -2
  48. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/static-ngeo/js/+package+module.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/js/{{cookiecutter.package}}module.js} +4 -4
  49. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/subscribers.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py} +1 -3
  50. c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
  51. c2cgeoportal_geoportal/scaffolds/{update/geoportal/CONST_Makefile_tmpl → advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile} +3 -27
  52. c2cgeoportal_geoportal/scaffolds/create/cookiecutter.json +18 -0
  53. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.dockerignore +14 -0
  54. c2cgeoportal_geoportal/scaffolds/create/{+dot+editorconfig → {{cookiecutter.project}}/.editorconfig} +2 -5
  55. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +57 -0
  56. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +46 -0
  57. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +66 -0
  58. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.gitignore +16 -0
  59. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierignore +1 -0
  60. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierrc.yaml +2 -0
  61. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +76 -0
  62. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +70 -0
  63. c2cgeoportal_geoportal/scaffolds/create/{README.rst_tmpl → {{cookiecutter.project}}/README.rst} +4 -4
  64. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +186 -0
  65. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +22 -0
  66. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
  67. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -0
  68. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +26 -0
  69. c2cgeoportal_geoportal/scaffolds/create/{docker-compose-lib.yaml → {{cookiecutter.project}}/docker-compose-lib.yaml} +165 -22
  70. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +23 -0
  71. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +66 -0
  72. c2cgeoportal_geoportal/scaffolds/create/{docker-compose.yaml → {{cookiecutter.project}}/docker-compose.yaml} +20 -15
  73. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +101 -0
  74. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +69 -0
  75. c2cgeoportal_geoportal/scaffolds/create/{geoportal/vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/vars.yaml} +126 -36
  76. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
  77. c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/Readme.txt +3 -3
  78. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/demo.map.tmpl +224 -0
  79. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +15 -0
  80. c2cgeoportal_geoportal/scaffolds/create/{mapserver/mapserver.map.tmpl_tmpl → {{cookiecutter.project}}/mapserver/mapserver.map.tmpl} +9 -18
  81. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Landscape.jrxml +13 -8
  82. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Portrait.jrxml +13 -8
  83. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Landscape.jrxml +13 -8
  84. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Portrait.jrxml +13 -8
  85. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/config.yaml.tmpl +11 -4
  86. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation.properties +4 -0
  87. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation_fr.properties +4 -0
  88. c2cgeoportal_geoportal/scaffolds/create/{project.yaml_tmpl → {{cookiecutter.project}}/project.yaml} +6 -6
  89. c2cgeoportal_geoportal/scaffolds/create/{pyproject.toml → {{cookiecutter.project}}/pyproject.toml} +4 -0
  90. c2cgeoportal_geoportal/scaffolds/create/{qgisserver/pg_service.conf.tmpl_tmpl → {{cookiecutter.project}}/qgisserver/pg_service.conf.tmpl} +2 -2
  91. c2cgeoportal_geoportal/scaffolds/create/{run_alembic.sh → {{cookiecutter.project}}/run_alembic.sh} +3 -5
  92. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +110 -0
  93. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +114 -0
  94. c2cgeoportal_geoportal/scaffolds/create/{setup.cfg_tmpl → {{cookiecutter.project}}/setup.cfg} +1 -1
  95. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +5 -0
  96. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/__init__.py +0 -0
  97. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/test_app.py +38 -0
  98. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tilegeneration/config.yaml.tmpl +195 -0
  99. c2cgeoportal_geoportal/scaffolds/update/cookiecutter.json +18 -0
  100. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/.upgrade.yaml +61 -0
  101. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +273 -0
  102. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
  103. c2cgeoportal_geoportal/scaffolds/update/{geoportal → {{cookiecutter.project}}/geoportal}/CONST_config-schema.yaml +64 -17
  104. c2cgeoportal_geoportal/scaffolds/update/{geoportal/CONST_vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/CONST_vars.yaml} +396 -19
  105. c2cgeoportal_geoportal/scripts/__init__.py +16 -30
  106. c2cgeoportal_geoportal/scripts/c2cupgrade.py +272 -234
  107. c2cgeoportal_geoportal/scripts/create_demo_theme.py +3 -6
  108. c2cgeoportal_geoportal/scripts/manage_users.py +34 -39
  109. c2cgeoportal_geoportal/scripts/pcreate.py +310 -0
  110. c2cgeoportal_geoportal/scripts/theme2fts.py +128 -24
  111. c2cgeoportal_geoportal/scripts/urllogin.py +19 -11
  112. c2cgeoportal_geoportal/templates/login.html +88 -84
  113. c2cgeoportal_geoportal/templates/notlogin.html +59 -59
  114. c2cgeoportal_geoportal/templates/testi18n.html +6 -8
  115. c2cgeoportal_geoportal/views/__init__.py +23 -6
  116. c2cgeoportal_geoportal/views/dev.py +9 -7
  117. c2cgeoportal_geoportal/views/dynamic.py +56 -19
  118. c2cgeoportal_geoportal/views/entry.py +85 -24
  119. c2cgeoportal_geoportal/views/fulltextsearch.py +29 -23
  120. c2cgeoportal_geoportal/views/geometry_processing.py +17 -9
  121. c2cgeoportal_geoportal/views/i18n.py +91 -9
  122. c2cgeoportal_geoportal/views/layers.py +166 -133
  123. c2cgeoportal_geoportal/views/login.py +161 -93
  124. c2cgeoportal_geoportal/views/mapserverproxy.py +47 -31
  125. c2cgeoportal_geoportal/views/memory.py +12 -12
  126. c2cgeoportal_geoportal/views/ogcproxy.py +52 -30
  127. c2cgeoportal_geoportal/views/pdfreport.py +30 -26
  128. c2cgeoportal_geoportal/views/printproxy.py +60 -52
  129. c2cgeoportal_geoportal/views/profile.py +24 -23
  130. c2cgeoportal_geoportal/views/proxy.py +88 -72
  131. c2cgeoportal_geoportal/views/raster.py +37 -26
  132. c2cgeoportal_geoportal/views/resourceproxy.py +13 -11
  133. c2cgeoportal_geoportal/views/shortener.py +27 -25
  134. c2cgeoportal_geoportal/views/theme.py +472 -332
  135. c2cgeoportal_geoportal/views/tinyowsproxy.py +42 -44
  136. c2cgeoportal_geoportal/views/vector_tiles.py +80 -0
  137. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/METADATA +19 -8
  138. c2cgeoportal_geoportal-2.8.1.180.dist-info/RECORD +191 -0
  139. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/WHEEL +1 -1
  140. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/entry_points.txt +3 -0
  141. tests/__init__.py +10 -5
  142. tests/test_cachebuster.py +3 -5
  143. tests/test_caching.py +18 -26
  144. tests/test_checker.py +1 -3
  145. tests/test_decimaljson.py +5 -5
  146. tests/test_headerstween.py +1 -3
  147. tests/test_i18n.py +2 -2
  148. tests/test_init.py +16 -20
  149. tests/test_locale_negociator.py +4 -6
  150. tests/test_mapserverproxy_route_predicate.py +1 -4
  151. tests/test_raster.py +15 -17
  152. tests/test_wmstparsing.py +10 -12
  153. tests/xmlstr.py +1 -3
  154. c2cgeoportal_geoportal/scaffolds/__init__.py +0 -227
  155. c2cgeoportal_geoportal/scaffolds/create/+dot+dockerignore_tmpl +0 -12
  156. c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/main.yaml_tmpl +0 -89
  157. c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/rebuild.yaml_tmpl +0 -78
  158. c2cgeoportal_geoportal/scaffolds/create/+dot+gitignore_tmpl +0 -16
  159. c2cgeoportal_geoportal/scaffolds/create/Dockerfile_tmpl +0 -67
  160. c2cgeoportal_geoportal/scaffolds/create/Makefile +0 -3
  161. c2cgeoportal_geoportal/scaffolds/create/build_tmpl +0 -167
  162. c2cgeoportal_geoportal/scaffolds/create/ci/config.yaml_tmpl +0 -23
  163. c2cgeoportal_geoportal/scaffolds/create/ci/requirements.txt +0 -1
  164. c2cgeoportal_geoportal/scaffolds/create/ci/trigger +0 -68
  165. c2cgeoportal_geoportal/scaffolds/create/docker-compose.override.sample.yaml +0 -54
  166. c2cgeoportal_geoportal/scaffolds/create/env.default_tmpl +0 -67
  167. c2cgeoportal_geoportal/scaffolds/create/env.project_tmpl +0 -48
  168. c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+dockerignore_tmpl +0 -6
  169. c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+eslintrc_tmpl +0 -15
  170. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/__init__.py_tmpl +0 -58
  171. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/models.py_tmpl +0 -10
  172. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/robot.txt +0 -3
  173. c2cgeoportal_geoportal/scaffolds/create/geoportal/production.ini_tmpl +0 -106
  174. c2cgeoportal_geoportal/scaffolds/create/geoportal/tools/extract-messages.js +0 -39
  175. c2cgeoportal_geoportal/scaffolds/create/geoportal/tsconfig.json_tmpl +0 -9
  176. c2cgeoportal_geoportal/scaffolds/create/geoportal/webpack.api.js_tmpl +0 -72
  177. c2cgeoportal_geoportal/scaffolds/create/mapserver/demo.map.tmpl_tmpl +0 -262
  178. c2cgeoportal_geoportal/scaffolds/create/mapserver/tinyows.xml +0 -36
  179. c2cgeoportal_geoportal/scaffolds/create/print/print-apps/+package+/config.yaml +0 -168
  180. c2cgeoportal_geoportal/scaffolds/create/qgisserver/geomapfish.yaml.tmpl_tmpl +0 -16
  181. c2cgeoportal_geoportal/scaffolds/create/spell-ignore-words.txt +0 -1
  182. c2cgeoportal_geoportal/scaffolds/create/tilegeneration/config.yaml.tmpl_tmpl +0 -185
  183. c2cgeoportal_geoportal/scaffolds/create/yamllint.yaml +0 -11
  184. c2cgeoportal_geoportal/scaffolds/update/+dot+upgrade.yaml_tmpl +0 -181
  185. c2cgeoportal_geoportal/scaffolds/update/CONST_CHANGELOG.txt_tmpl +0 -454
  186. c2cgeoportal_geoportal/templates/dynamic.js +0 -21
  187. c2cgeoportal_geoportal-2.6.0.dist-info/RECORD +0 -173
  188. /c2cgeoportal_geoportal/{scaffolds/create/geoportal/+package+_geoportal/static/css/desktop.css → py.typed} +0 -0
  189. /c2cgeoportal_geoportal/scaffolds/{create/geoportal/Makefile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Makefile} +0 -0
  190. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/alembic.ini +0 -0
  191. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/language_mapping +0 -0
  192. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-server.cfg +0 -0
  193. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/requirements.txt +0 -0
  194. /c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/views/__init__.py +0 -0
  195. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/locale/en/LC_MESSAGES/+package+_geoportal-client.po → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/locale/en/LC_MESSAGES/{{cookiecutter.package}}_geoportal-client.po} +0 -0
  196. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/iframe_api.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/desktop.css} +0 -0
  197. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/mobile.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/iframe_api.css} +0 -0
  198. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_left.png +0 -0
  199. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_right.png +0 -0
  200. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/blank.png +0 -0
  201. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-blue.png +0 -0
  202. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-gold.png +0 -0
  203. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-green.png +0 -0
  204. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker.png +0 -0
  205. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/robot.txt.tmpl +0 -0
  206. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/TM_EUROPE_BORDERS-0.3.sql +0 -0
  207. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arial.ttf +0 -0
  208. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbd.ttf +0 -0
  209. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbi.ttf +0 -0
  210. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Ariali.ttf +0 -0
  211. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Bold.ttf +0 -0
  212. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-BoldItalic.ttf +0 -0
  213. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Italic.ttf +0 -0
  214. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Regular.ttf +0 -0
  215. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdana.ttf +0 -0
  216. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanab.ttf +0 -0
  217. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanai.ttf +0 -0
  218. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanaz.ttf +0 -0
  219. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts.conf +0 -0
  220. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/tinyows.xml.tmpl +0 -0
  221. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/legend.jrxml +0 -0
  222. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/logo.png +0 -0
  223. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/north.svg +0 -0
  224. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/results.jrxml +0 -0
  225. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2011-2021, Camptocamp SA
1
+ # Copyright (c) 2011-2024, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -32,10 +30,13 @@ import datetime
32
30
  import ipaddress
33
31
  import json
34
32
  import logging
33
+ import re
35
34
  from string import Formatter
36
- from typing import Any, Dict, List, Set, Union
35
+ from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union, cast
37
36
 
38
37
  import dateutil
38
+ import pyramid.request
39
+ import pyramid.response
39
40
  from pyramid.interfaces import IRoutePregenerator
40
41
  from zope.interface import implementer
41
42
 
@@ -48,18 +49,25 @@ CACHE_REGION = get_region("std")
48
49
  CACHE_REGION_OBJ = get_region("obj")
49
50
 
50
51
 
51
- def get_types_map(types_array):
52
+ def get_types_map(types_array: List[Dict[str, Any]]) -> Dict[str, Dict[str, Any]]:
53
+ """Get the type name of a metadata or a functionality."""
52
54
  return {type_["name"]: type_ for type_ in types_array}
53
55
 
54
56
 
55
57
  def get_typed(
56
- name, value, types, request, errors, layer_name=None
58
+ name: str,
59
+ value: str,
60
+ types: Dict[str, Any],
61
+ request: pyramid.request.Request,
62
+ errors: Set[str],
63
+ layer_name: Optional[str] = None,
57
64
  ) -> Union[str, int, float, bool, None, List[Any], Dict[str, Any]]:
58
- prefix = "Layer '{}': ".format(layer_name) if layer_name is not None else ""
65
+ """Get the typed (parsed) value of a metadata or a functionality."""
66
+ prefix = f"Layer '{layer_name}': " if layer_name is not None else ""
59
67
  type_ = {"type": "not init"}
60
68
  try:
61
69
  if name not in types:
62
- errors.add("{}Type '{}' not defined.".format(prefix, name))
70
+ errors.add(f"{prefix}Type '{name}' not defined.")
63
71
  return None
64
72
  type_ = types[name]
65
73
  if type_.get("type", "string") == "string":
@@ -73,8 +81,8 @@ def get_typed(
73
81
  if value in ["no", "n", "off", "0", "false"]:
74
82
  return False
75
83
  errors.add(
76
- "{}The boolean attribute '{}'='{}' is not in "
77
- "[yes, y, on, 1, true, no, n, off, 0, false].".format(prefix, name, value.lower())
84
+ f"{prefix}The boolean attribute '{name}'='{value.lower()}' is not in "
85
+ "[yes, y, on, 1, true, no, n, off, 0, false]."
78
86
  )
79
87
  elif type_["type"] == "integer":
80
88
  return int(value)
@@ -83,43 +91,47 @@ def get_typed(
83
91
  elif type_["type"] == "date":
84
92
  date = dateutil.parser.parse(value, default=datetime.datetime(1, 1, 1, 0, 0, 0)) # type: ignore
85
93
  if date.time() != datetime.time(0, 0, 0):
86
- errors.add(
87
- "{}The date attribute '{}'='{}' should not have any time".format(prefix, name, value)
88
- )
94
+ errors.add(f"{prefix}The date attribute '{name}'='{value}' should not have any time")
89
95
  else:
90
96
  return datetime.date.strftime(date.date(), "%Y-%m-%d")
91
97
  elif type_["type"] == "time":
92
98
  date = dateutil.parser.parse(value, default=datetime.datetime(1, 1, 1, 0, 0, 0)) # type: ignore
93
99
  if date.date() != datetime.date(1, 1, 1):
94
- errors.add(
95
- "{}The time attribute '{}'='{}' should not have any date".format(prefix, name, value)
96
- )
100
+ errors.add(f"{prefix}The time attribute '{name}'='{value}' should not have any date")
97
101
  else:
98
102
  return datetime.time.strftime(date.time(), "%H:%M:%S")
99
103
  elif type_["type"] == "datetime":
100
104
  date = dateutil.parser.parse(value, default=datetime.datetime(1, 1, 1, 0, 0, 0)) # type: ignore
101
105
  return datetime.datetime.strftime(date, "%Y-%m-%dT%H:%M:%S")
102
106
  elif type_["type"] == "url":
103
- return get_url2("{}The attribute '{}'".format(prefix, name), value, request, errors)
107
+ url = get_url2(f"{prefix}The attribute '{name}'", value, request, errors)
108
+ return url.url() if url else ""
104
109
  elif type_["type"] == "json":
105
110
  try:
106
- return json.loads(value)
111
+ return cast(Dict[str, Any], json.loads(value))
107
112
  except Exception as e:
108
- errors.append(
109
- "{}The attribute '{}'='{}' has an error: {}".format(prefix, name, value, str(e))
113
+ errors.add(f"{prefix}The attribute '{name}'='{value}' has an error: {str(e)}")
114
+ elif type_["type"] == "regex":
115
+ pattern = type_["regex"]
116
+ if re.match(pattern, value) is None:
117
+ errors.add(
118
+ f"{prefix}The regex attribute '{name}'='{value}' "
119
+ f"does not match expected pattern '{pattern}'."
110
120
  )
121
+ else:
122
+ return value
111
123
  else:
112
- errors.add("{}Unknown type '{}'.".format(prefix, type_["type"]))
124
+ errors.add(f"{prefix}Unknown type '{type_['type']}'.")
113
125
  except Exception as e:
114
126
  errors.add(
115
- "{}Unable to parse the attribute '{}'='{}' with the type '{}', error:\n{}".format(
116
- prefix, name, value, type_.get("type", "string"), str(e)
117
- )
127
+ f"{prefix}Unable to parse the attribute '{name}'='{value}' with the type "
128
+ f"'{type_.get('type', 'string')}', error:\n{e!s}"
118
129
  )
119
130
  return None
120
131
 
121
132
 
122
- def get_setting(settings, path, default=None):
133
+ def get_setting(settings: Any, path: Iterable[str], default: Any = None) -> Any:
134
+ """Get the settings."""
123
135
  value = settings
124
136
  for p in path:
125
137
  if value and p in value:
@@ -129,42 +141,48 @@ def get_setting(settings, path, default=None):
129
141
  return value if value else default
130
142
 
131
143
 
132
- @CACHE_REGION_OBJ.cache_on_arguments()
133
- def get_ogc_server_wms_url_ids(request):
144
+ @CACHE_REGION_OBJ.cache_on_arguments() # type: ignore
145
+ def get_ogc_server_wms_url_ids(request: pyramid.request.Request, host: str) -> Dict[str, List[int]]:
146
+ """Get the OGCServer ids mapped on the WMS URL."""
134
147
  from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
135
148
  from c2cgeoportal_commons.models.main import OGCServer # pylint: disable=import-outside-toplevel
136
149
 
150
+ del host # used for cache
137
151
  errors: Set[str] = set()
138
152
  servers: Dict[str, List[int]] = {}
139
153
  for ogc_server in DBSession.query(OGCServer).all():
140
154
  url = get_url2(ogc_server.name, ogc_server.url, request, errors)
141
155
  if url is not None:
142
- servers.setdefault(url, []).append(ogc_server.id)
156
+ servers.setdefault(url.url(), []).append(ogc_server.id)
143
157
  return servers
144
158
 
145
159
 
146
- @CACHE_REGION_OBJ.cache_on_arguments()
147
- def get_ogc_server_wfs_url_ids(request):
160
+ @CACHE_REGION_OBJ.cache_on_arguments() # type: ignore
161
+ def get_ogc_server_wfs_url_ids(request: pyramid.request.Request, host: str) -> Dict[str, List[int]]:
162
+ """Get the OGCServer ids mapped on the WFS URL."""
148
163
  from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
149
164
  from c2cgeoportal_commons.models.main import OGCServer # pylint: disable=import-outside-toplevel
150
165
 
166
+ del host # used for cache
151
167
  errors: Set[str] = set()
152
168
  servers: Dict[str, List[int]] = {}
153
169
  for ogc_server in DBSession.query(OGCServer).all():
154
170
  url = get_url2(ogc_server.name, ogc_server.url_wfs or ogc_server.url, request, errors)
155
171
  if url is not None:
156
- servers.setdefault(url, []).append(ogc_server.id)
172
+ servers.setdefault(url.url(), []).append(ogc_server.id)
157
173
  return servers
158
174
 
159
175
 
160
176
  @implementer(IRoutePregenerator)
161
- class C2CPregenerator: # pragma: no cover
162
- def __init__(self, version=True, role=False):
177
+ class C2CPregenerator:
178
+ """The custom pyramid pregenerator that manage the cache version."""
179
+
180
+ def __init__(self, version: bool = True, role: bool = False):
163
181
  self.version = version
164
182
  self.role = role
165
183
 
166
- def __call__(self, request, elements, kw):
167
- query = kw.get("_query", {})
184
+ def __call__(self, request: pyramid.request.Request, elements: Any, kw: Any) -> Tuple[Any, Any]:
185
+ query = {**kw.get("_query", {})}
168
186
 
169
187
  if self.version:
170
188
  query["cache_version"] = get_cache_version()
@@ -182,22 +200,26 @@ class C2CPregenerator: # pragma: no cover
182
200
  _formatter = Formatter()
183
201
 
184
202
 
185
- @CACHE_REGION_OBJ.cache_on_arguments()
186
- def _get_intranet_networks(request):
203
+ @CACHE_REGION_OBJ.cache_on_arguments() # type: ignore
204
+ def _get_intranet_networks(
205
+ request: pyramid.request.Request,
206
+ ) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
187
207
  return [
188
208
  ipaddress.ip_network(network, strict=False)
189
209
  for network in request.registry.settings.get("intranet", {}).get("networks", [])
190
210
  ]
191
211
 
192
212
 
193
- @CACHE_REGION.cache_on_arguments()
194
- def get_role_id(name):
213
+ @CACHE_REGION.cache_on_arguments() # type: ignore
214
+ def get_role_id(name: str) -> int:
215
+ """Get the role ID."""
195
216
  from c2cgeoportal_commons.models import DBSession, main # pylint: disable=import-outside-toplevel
196
217
 
197
- return DBSession.query(main.Role.id).filter(main.Role.name == name).one()[0]
218
+ return cast(int, DBSession.query(main.Role.id).filter(main.Role.name == name).one()[0])
198
219
 
199
220
 
200
- def get_roles_id(request):
221
+ def get_roles_id(request: pyramid.request.Request) -> List[int]:
222
+ """Get the user roles ID."""
201
223
  result = [get_role_id(request.get_organization_role("anonymous"))]
202
224
  if is_intranet(request):
203
225
  result.append(get_role_id(request.get_organization_role("intranet")))
@@ -207,7 +229,8 @@ def get_roles_id(request):
207
229
  return result
208
230
 
209
231
 
210
- def get_roles_name(request):
232
+ def get_roles_name(request: pyramid.request.Request) -> pyramid.response.Response:
233
+ """Get the user roles name."""
211
234
  result = [request.get_organization_role("anonymous")]
212
235
  if is_intranet(request):
213
236
  result.append(request.get_organization_role("intranet"))
@@ -217,7 +240,8 @@ def get_roles_name(request):
217
240
  return result
218
241
 
219
242
 
220
- def is_intranet(request):
243
+ def is_intranet(request: pyramid.request.Request) -> bool:
244
+ """Get if it's an intranet user."""
221
245
  address = ipaddress.ip_address(request.client_addr)
222
246
  for network in _get_intranet_networks(request):
223
247
  if address in network:
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2014-2021, Camptocamp SA
1
+ # Copyright (c) 2014-2023, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -31,8 +29,11 @@
31
29
  import binascii
32
30
  import json
33
31
  import logging
32
+ import os
34
33
  import time
34
+ from typing import Any, Callable, Dict, List, Optional, cast
35
35
 
36
+ import pyramid.request
36
37
  from Crypto.Cipher import AES # nosec
37
38
  from pyramid.authentication import (
38
39
  AuthTktAuthenticationPolicy,
@@ -51,13 +52,17 @@ LOG = logging.getLogger(__name__)
51
52
 
52
53
 
53
54
  @implementer(IAuthenticationPolicy)
54
- class UrlAuthenticationPolicy(CallbackAuthenticationPolicy):
55
- def __init__(self, aes_key, callback=None, debug=False):
55
+ class UrlAuthenticationPolicy(CallbackAuthenticationPolicy): # type: ignore
56
+ """An authentication policy based on information given in the URL."""
57
+
58
+ def __init__(
59
+ self, aes_key: str, callback: Optional[Callable[[str, Any], List[str]]] = None, debug: bool = False
60
+ ):
56
61
  self.aeskey = aes_key
57
62
  self.callback = callback
58
63
  self.debug = debug
59
64
 
60
- def unauthenticated_userid(self, request):
65
+ def unauthenticated_userid(self, request: pyramid.request.Request) -> Optional[str]:
61
66
  if not request.method == "GET" or "auth" not in request.params:
62
67
  return None
63
68
  auth_enc = request.params.get("auth")
@@ -65,14 +70,14 @@ class UrlAuthenticationPolicy(CallbackAuthenticationPolicy):
65
70
  return None
66
71
  try:
67
72
  if self.aeskey is None: # pragma: nocover
68
- raise Exception("urllogin is not configured")
73
+ raise Exception("urllogin is not configured") # pylint: disable=broad-exception-raised
69
74
  now = int(time.time())
70
75
  data = binascii.unhexlify(auth_enc.encode("ascii"))
71
76
  nonce = data[0:16]
72
77
  tag = data[16:32]
73
78
  ciphertext = data[32:]
74
79
  cipher = AES.new(self.aeskey.encode("ascii"), AES.MODE_EAX, nonce)
75
- auth = json.loads(cipher.decrypt_and_verify(ciphertext, tag).decode("utf-8")) # type: ignore
80
+ auth = json.loads(cipher.decrypt_and_verify(ciphertext, tag).decode("utf-8"))
76
81
 
77
82
  if "t" in auth and "u" in auth and "p" in auth:
78
83
  timestamp = int(auth["t"])
@@ -80,33 +85,35 @@ class UrlAuthenticationPolicy(CallbackAuthenticationPolicy):
80
85
  if now < timestamp and request.registry.validate_user(request, auth["u"], auth["p"]):
81
86
  headers = remember(request, auth["u"])
82
87
  request.response.headerlist.extend(headers)
83
- return auth["u"]
88
+ return cast(str, auth["u"])
84
89
 
85
90
  except Exception as e:
86
91
  LOG.error("URL login error: %s.", e, exc_info=True)
87
92
 
88
93
  return None
89
94
 
90
- def remember(self, request, userid, **kw): # pylint: disable=no-self-use
91
- """A no-op."""
95
+ def remember(self, request: pyramid.request.Request, userid: str, **kw: Any) -> List[Dict[str, str]]:
96
+ """Do no-op."""
92
97
  del request, userid, kw
93
98
  return []
94
99
 
95
- def forget(self, request): # pylint: disable= no-self-use
96
- """A no-op."""
100
+ def forget(self, request: pyramid.request.Request) -> List[Dict[str, str]]:
101
+ """Do no-op."""
97
102
  del request
98
103
  return []
99
104
 
100
105
 
101
106
  @implementer(IAuthenticationPolicy)
102
- class OAuth2AuthenticationPolicy(CallbackAuthenticationPolicy):
107
+ class OAuth2AuthenticationPolicy(CallbackAuthenticationPolicy): # type: ignore
108
+ """The oauth2 authentication policy."""
109
+
103
110
  @staticmethod
104
- def unauthenticated_userid(request):
111
+ def unauthenticated_userid(request: pyramid.request.Request) -> Optional[str]:
105
112
  route_url = ""
106
113
  try:
107
- route_url = request.current_route_url(_query=request.GET)
114
+ route_url = request.current_route_url(_query={**request.GET})
108
115
  except ValueError:
109
- route_url = request.route_url("base", _query=request.GET)
116
+ route_url = request.route_url("base", _query={**request.GET})
110
117
 
111
118
  LOG.debug(
112
119
  "Call OAuth verify_request with:\nurl: %s\nmethod: %s\nbody:\n%s",
@@ -125,21 +132,33 @@ class OAuth2AuthenticationPolicy(CallbackAuthenticationPolicy):
125
132
  if valid:
126
133
  request.user_ = oauth2_request.user
127
134
 
128
- return request.user_.username
135
+ return cast(str, request.user.username)
129
136
  return None
130
137
 
131
- def remember(self, request, userid, **kw): # pylint: disable=no-self-use
132
- """A no-op."""
138
+ def remember(self, request: pyramid.request.Request, userid: str, **kw: Any) -> List[Dict[str, str]]:
139
+ """Do no-op."""
133
140
  del request, userid, kw
134
141
  return []
135
142
 
136
- def forget(self, request): # pylint: disable= no-self-use
137
- """A no-op."""
143
+ def forget(self, request: pyramid.request.Request) -> List[Dict[str, str]]:
144
+ """Do no-op."""
138
145
  del request
139
146
  return []
140
147
 
141
148
 
142
- def create_authentication(settings):
149
+ @implementer(IAuthenticationPolicy)
150
+ class DevAuthenticationPolicy(CallbackAuthenticationPolicy): # type: ignore
151
+ """An authentication policy for the dev base on an environment variable."""
152
+
153
+ @staticmethod
154
+ def unauthenticated_userid(request: pyramid.request.Request) -> Optional[str]:
155
+ """Get the user name from the environment variable."""
156
+ del request
157
+ return os.environ["DEV_LOGINNAME"]
158
+
159
+
160
+ def create_authentication(settings: Dict[str, Any]) -> MultiAuthenticationPolicy:
161
+ """Create all the authentication policies."""
143
162
  timeout = settings.get("authtkt_timeout")
144
163
  timeout = None if timeout is None or timeout.lower() == "none" else int(timeout)
145
164
  reissue_time = settings.get("authtkt_reissue_time")
@@ -154,7 +173,7 @@ def create_authentication(settings):
154
173
  secret = settings["authtkt_secret"]
155
174
  basicauth = settings.get("basicauth", "False").lower() in ("true", "yes", "1")
156
175
  if len(secret) < 64:
157
- raise Exception(
176
+ raise Exception( # pylint: disable=broad-exception-raised
158
177
  '"authtkt_secret should be at least 64 characters.'
159
178
  "See https://docs.pylonsproject.org/projects/pyramid/en/latest/api/session.html"
160
179
  )
@@ -188,17 +207,22 @@ def create_authentication(settings):
188
207
  if basicauth:
189
208
  if settings["authentication"].get("two_factor", False):
190
209
  LOG.warning(
191
- "Basic auth and tow factor auth should not be anhable toogether, "
210
+ "Basic auth and two factor auth should not be enable together, "
192
211
  "you should use OAuth2 instead of Basic auth"
193
212
  )
194
213
 
195
214
  basic_authentication_policy = BasicAuthAuthenticationPolicy(c2cgeoportal_check)
196
215
  policies.append(basic_authentication_policy)
197
216
 
217
+ # Consider empty string as not configured
218
+ if "DEV_LOGINNAME" in os.environ and os.environ["DEV_LOGINNAME"]:
219
+ policies.append(DevAuthenticationPolicy())
220
+
198
221
  return MultiAuthenticationPolicy(policies)
199
222
 
200
223
 
201
- def c2cgeoportal_check(username, password, request): # pragma: no cover
224
+ def c2cgeoportal_check(username: str, password: str, request: pyramid.request.Request) -> Optional[List[str]]:
225
+ """Check the user authentication."""
202
226
  if request.registry.validate_user(request, username, password):
203
227
  return defaultgroupsfinder(username, request)
204
228
  return None
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2013-2020, Camptocamp SA
1
+ # Copyright (c) 2013-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -27,16 +25,22 @@
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
 
28
+ from enum import Enum
29
+
30
+
31
+ class Color(Enum):
32
+ """The available colors."""
30
33
 
31
- BLACK = 0
32
- RED = 1
33
- GREEN = 2
34
- YELLOW = 3
35
- BLUE = 4
36
- MAGENTA = 5
37
- CYAN = 6
38
- WHITE = 7
34
+ BLACK = 0
35
+ RED = 1
36
+ GREEN = 2
37
+ YELLOW = 3
38
+ BLUE = 4
39
+ MAGENTA = 5
40
+ CYAN = 6
41
+ WHITE = 7
39
42
 
40
43
 
41
- def colorize(text, color): # pragma: no cover
42
- return "\x1b[01;3{0:d}m{1!s}\x1b[0m".format(color, text)
44
+ def colorize(text: str, color: Color) -> str:
45
+ """Colorize a text for the bash."""
46
+ return f"\x1b[01;3{color.value}m{text}\x1b[0m"
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  # Copyright (c) 2011-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
@@ -29,22 +27,28 @@
29
27
 
30
28
 
31
29
  import uuid
30
+ from typing import Any, Callable, Dict, Tuple
32
31
  from urllib.parse import urljoin
33
32
 
34
33
  import pyramid.registry
34
+ import pyramid.request
35
+ import pyramid.response
35
36
 
36
37
  from c2cgeoportal_geoportal.lib.caching import get_region
37
38
 
38
39
  CACHE_REGION = get_region("std")
39
40
 
40
41
 
41
- @CACHE_REGION.cache_on_arguments()
42
- def get_cache_version():
43
- """Return a cache version that is regenerate after each cache invalidation"""
42
+ @CACHE_REGION.cache_on_arguments() # type: ignore
43
+ def get_cache_version() -> str:
44
+ """Return a cache version that is regenerate after each cache invalidation."""
44
45
  return uuid.uuid4().hex
45
46
 
46
47
 
47
- def version_cache_buster(request, subpath, kw): # pragma: no cover
48
+ def version_cache_buster(
49
+ request: pyramid.request.Request, subpath: str, kw: Dict[str, Any]
50
+ ) -> Tuple[str, Dict[str, Any]]:
51
+ """Join the cash buster version with the sub path."""
48
52
  del request # unused
49
53
  return urljoin(get_cache_version() + "/", subpath), kw
50
54
 
@@ -52,11 +56,15 @@ def version_cache_buster(request, subpath, kw): # pragma: no cover
52
56
  class CachebusterTween:
53
57
  """Get back the cachebuster URL."""
54
58
 
55
- def __init__(self, handler, registry: pyramid.registry.Registry):
59
+ def __init__(
60
+ self,
61
+ handler: Callable[[pyramid.request.Request], pyramid.response.Response],
62
+ registry: pyramid.registry.Registry,
63
+ ):
56
64
  self.handler = handler
57
65
  self.cache_path = registry.settings["cache_path"]
58
66
 
59
- def __call__(self, request):
67
+ def __call__(self, request: pyramid.request.Request) -> pyramid.response.Response:
60
68
  path = request.path_info.split("/")
61
69
  if len(path) > 1 and path[1] in self.cache_path:
62
70
  # remove the cache buster