c2cgeoportal-geoportal 2.6.0__py2.py3-none-any.whl → 2.7.1.157__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 (212) hide show
  1. c2cgeoportal_geoportal/__init__.py +224 -84
  2. c2cgeoportal_geoportal/lib/__init__.py +67 -43
  3. c2cgeoportal_geoportal/lib/authentication.py +50 -22
  4. c2cgeoportal_geoportal/lib/bashcolor.py +17 -13
  5. c2cgeoportal_geoportal/lib/cacheversion.py +16 -8
  6. c2cgeoportal_geoportal/lib/caching.py +61 -191
  7. c2cgeoportal_geoportal/lib/check_collector.py +17 -10
  8. c2cgeoportal_geoportal/lib/checker.py +61 -63
  9. c2cgeoportal_geoportal/lib/common_headers.py +170 -0
  10. c2cgeoportal_geoportal/lib/dbreflection.py +54 -39
  11. c2cgeoportal_geoportal/lib/filter_capabilities.py +122 -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 +361 -237
  18. c2cgeoportal_geoportal/lib/loader.py +10 -15
  19. c2cgeoportal_geoportal/lib/metrics.py +28 -17
  20. c2cgeoportal_geoportal/lib/oauth2.py +214 -145
  21. c2cgeoportal_geoportal/lib/wmstparsing.py +115 -90
  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} +18 -9
  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 +102 -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/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +2 -0
  36. c2cgeoportal_geoportal/scaffolds/{create/geoportal/setup.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/setup.py} +6 -7
  37. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/tools/extract-messages.js +8 -6
  38. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tsconfig.json +8 -0
  39. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +75 -0
  40. c2cgeoportal_geoportal/scaffolds/{create/geoportal/webpack.apps.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js} +31 -28
  41. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.commons.js +3 -7
  42. c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.config.js +1 -1
  43. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/__init__.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py} +11 -22
  44. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/authentication.py +10 -0
  45. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/dev.py +14 -0
  46. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/models.py +8 -0
  47. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/multi_organization.py +7 -0
  48. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/resources.py +4 -3
  49. 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
  50. 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
  51. c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/subscribers.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py} +1 -3
  52. c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
  53. c2cgeoportal_geoportal/scaffolds/{update/geoportal/CONST_Makefile_tmpl → advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile} +3 -7
  54. c2cgeoportal_geoportal/scaffolds/create/cookiecutter.json +18 -0
  55. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.dockerignore +14 -0
  56. c2cgeoportal_geoportal/scaffolds/create/{+dot+editorconfig → {{cookiecutter.project}}/.editorconfig} +2 -5
  57. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +43 -0
  58. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +46 -0
  59. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +65 -0
  60. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.gitignore +16 -0
  61. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierignore +1 -0
  62. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierrc.yaml +2 -0
  63. c2cgeoportal_geoportal/scaffolds/create/{Dockerfile_tmpl → {{cookiecutter.project}}/Dockerfile} +20 -11
  64. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +14 -0
  65. c2cgeoportal_geoportal/scaffolds/create/{README.rst_tmpl → {{cookiecutter.project}}/README.rst} +4 -4
  66. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +162 -0
  67. c2cgeoportal_geoportal/scaffolds/create/{ci/config.yaml_tmpl → {{cookiecutter.project}}/ci/config.yaml} +7 -5
  68. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -0
  69. c2cgeoportal_geoportal/scaffolds/create/{docker-compose-lib.yaml → {{cookiecutter.project}}/docker-compose-lib.yaml} +133 -17
  70. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +67 -0
  71. c2cgeoportal_geoportal/scaffolds/create/{docker-compose.yaml → {{cookiecutter.project}}/docker-compose.yaml} +17 -12
  72. c2cgeoportal_geoportal/scaffolds/create/{env.default_tmpl → {{cookiecutter.project}}/env.default} +29 -14
  73. c2cgeoportal_geoportal/scaffolds/create/{env.project_tmpl → {{cookiecutter.project}}/env.project} +16 -4
  74. c2cgeoportal_geoportal/scaffolds/create/{geoportal/vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/vars.yaml} +93 -27
  75. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
  76. c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/Readme.txt +1 -1
  77. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/demo.map.tmpl +224 -0
  78. c2cgeoportal_geoportal/scaffolds/create/{mapserver/mapserver.map.tmpl_tmpl → {{cookiecutter.project}}/mapserver/mapserver.map.tmpl} +7 -15
  79. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Landscape.jrxml +8 -8
  80. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Portrait.jrxml +8 -8
  81. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Landscape.jrxml +8 -8
  82. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Portrait.jrxml +8 -8
  83. c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/config.yaml.tmpl +5 -4
  84. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation.properties +4 -0
  85. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation_fr.properties +4 -0
  86. c2cgeoportal_geoportal/scaffolds/create/{project.yaml_tmpl → {{cookiecutter.project}}/project.yaml} +6 -6
  87. c2cgeoportal_geoportal/scaffolds/create/{qgisserver/pg_service.conf.tmpl_tmpl → {{cookiecutter.project}}/qgisserver/pg_service.conf.tmpl} +2 -2
  88. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +110 -0
  89. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +114 -0
  90. c2cgeoportal_geoportal/scaffolds/create/{setup.cfg_tmpl → {{cookiecutter.project}}/setup.cfg} +1 -1
  91. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +3 -0
  92. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tilegeneration/config.yaml.tmpl +195 -0
  93. c2cgeoportal_geoportal/scaffolds/update/cookiecutter.json +18 -0
  94. c2cgeoportal_geoportal/scaffolds/update/{+dot+upgrade.yaml_tmpl → {{cookiecutter.project}}/.upgrade.yaml} +49 -39
  95. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +1160 -0
  96. c2cgeoportal_geoportal/scaffolds/update/{geoportal → {{cookiecutter.project}}/geoportal}/CONST_config-schema.yaml +47 -2
  97. c2cgeoportal_geoportal/scaffolds/update/{geoportal/CONST_vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/CONST_vars.yaml} +350 -17
  98. c2cgeoportal_geoportal/scripts/__init__.py +16 -30
  99. c2cgeoportal_geoportal/scripts/c2cupgrade.py +271 -232
  100. c2cgeoportal_geoportal/scripts/create_demo_theme.py +3 -6
  101. c2cgeoportal_geoportal/scripts/manage_users.py +34 -39
  102. c2cgeoportal_geoportal/scripts/pcreate.py +312 -0
  103. c2cgeoportal_geoportal/scripts/theme2fts.py +72 -23
  104. c2cgeoportal_geoportal/scripts/urllogin.py +19 -11
  105. c2cgeoportal_geoportal/templates/login.html +88 -84
  106. c2cgeoportal_geoportal/templates/notlogin.html +59 -59
  107. c2cgeoportal_geoportal/templates/testi18n.html +6 -8
  108. c2cgeoportal_geoportal/views/__init__.py +23 -4
  109. c2cgeoportal_geoportal/views/dev.py +9 -7
  110. c2cgeoportal_geoportal/views/dynamic.py +56 -19
  111. c2cgeoportal_geoportal/views/entry.py +93 -24
  112. c2cgeoportal_geoportal/views/fulltextsearch.py +28 -22
  113. c2cgeoportal_geoportal/views/geometry_processing.py +15 -7
  114. c2cgeoportal_geoportal/views/i18n.py +91 -9
  115. c2cgeoportal_geoportal/views/layers.py +160 -126
  116. c2cgeoportal_geoportal/views/login.py +106 -93
  117. c2cgeoportal_geoportal/views/mapserverproxy.py +46 -29
  118. c2cgeoportal_geoportal/views/memory.py +12 -12
  119. c2cgeoportal_geoportal/views/ogcproxy.py +48 -30
  120. c2cgeoportal_geoportal/views/pdfreport.py +26 -22
  121. c2cgeoportal_geoportal/views/printproxy.py +60 -52
  122. c2cgeoportal_geoportal/views/profile.py +24 -23
  123. c2cgeoportal_geoportal/views/proxy.py +87 -69
  124. c2cgeoportal_geoportal/views/raster.py +35 -24
  125. c2cgeoportal_geoportal/views/resourceproxy.py +13 -11
  126. c2cgeoportal_geoportal/views/shortener.py +27 -24
  127. c2cgeoportal_geoportal/views/theme.py +427 -321
  128. c2cgeoportal_geoportal/views/tinyowsproxy.py +46 -39
  129. c2cgeoportal_geoportal/views/vector_tiles.py +80 -0
  130. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.157.dist-info}/METADATA +25 -20
  131. c2cgeoportal_geoportal-2.7.1.157.dist-info/RECORD +185 -0
  132. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.157.dist-info}/WHEEL +1 -1
  133. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.157.dist-info}/entry_points.txt +3 -1
  134. tests/__init__.py +7 -3
  135. tests/test_cachebuster.py +0 -2
  136. tests/test_caching.py +17 -25
  137. tests/test_checker.py +0 -2
  138. tests/test_decimaljson.py +4 -4
  139. tests/test_headerstween.py +0 -2
  140. tests/test_i18n.py +1 -1
  141. tests/test_init.py +4 -7
  142. tests/test_locale_negociator.py +0 -2
  143. tests/test_mapserverproxy_route_predicate.py +0 -2
  144. tests/test_raster.py +0 -2
  145. tests/test_wmstparsing.py +0 -2
  146. c2cgeoportal_geoportal/scaffolds/__init__.py +0 -227
  147. c2cgeoportal_geoportal/scaffolds/create/+dot+dockerignore_tmpl +0 -12
  148. c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/main.yaml_tmpl +0 -89
  149. c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/rebuild.yaml_tmpl +0 -78
  150. c2cgeoportal_geoportal/scaffolds/create/+dot+gitignore_tmpl +0 -16
  151. c2cgeoportal_geoportal/scaffolds/create/Makefile +0 -3
  152. c2cgeoportal_geoportal/scaffolds/create/build_tmpl +0 -167
  153. c2cgeoportal_geoportal/scaffolds/create/ci/requirements.txt +0 -1
  154. c2cgeoportal_geoportal/scaffolds/create/ci/trigger +0 -68
  155. c2cgeoportal_geoportal/scaffolds/create/docker-compose.override.sample.yaml +0 -54
  156. c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+dockerignore_tmpl +0 -6
  157. c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+eslintrc_tmpl +0 -15
  158. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/models.py_tmpl +0 -10
  159. c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/robot.txt +0 -3
  160. c2cgeoportal_geoportal/scaffolds/create/geoportal/production.ini_tmpl +0 -106
  161. c2cgeoportal_geoportal/scaffolds/create/geoportal/requirements.txt +0 -2
  162. c2cgeoportal_geoportal/scaffolds/create/geoportal/tsconfig.json_tmpl +0 -9
  163. c2cgeoportal_geoportal/scaffolds/create/geoportal/webpack.api.js_tmpl +0 -72
  164. c2cgeoportal_geoportal/scaffolds/create/mapserver/demo.map.tmpl_tmpl +0 -262
  165. c2cgeoportal_geoportal/scaffolds/create/mapserver/tinyows.xml +0 -36
  166. c2cgeoportal_geoportal/scaffolds/create/print/print-apps/+package+/config.yaml +0 -168
  167. c2cgeoportal_geoportal/scaffolds/create/qgisserver/geomapfish.yaml.tmpl_tmpl +0 -16
  168. c2cgeoportal_geoportal/scaffolds/create/spell-ignore-words.txt +0 -1
  169. c2cgeoportal_geoportal/scaffolds/create/tilegeneration/config.yaml.tmpl_tmpl +0 -185
  170. c2cgeoportal_geoportal/scaffolds/create/yamllint.yaml +0 -11
  171. c2cgeoportal_geoportal/scaffolds/update/CONST_CHANGELOG.txt_tmpl +0 -454
  172. c2cgeoportal_geoportal/templates/dynamic.js +0 -21
  173. c2cgeoportal_geoportal-2.6.0.dist-info/RECORD +0 -173
  174. /c2cgeoportal_geoportal/{scaffolds/create/geoportal/+package+_geoportal/static/css/desktop.css → py.typed} +0 -0
  175. /c2cgeoportal_geoportal/scaffolds/{create/geoportal/Makefile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Makefile} +0 -0
  176. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/alembic.ini +0 -0
  177. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/language_mapping +0 -0
  178. /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-server.cfg +0 -0
  179. /c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/views/__init__.py +0 -0
  180. /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
  181. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/iframe_api.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/desktop.css} +0 -0
  182. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/mobile.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/iframe_api.css} +0 -0
  183. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_left.png +0 -0
  184. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_right.png +0 -0
  185. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/blank.png +0 -0
  186. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-blue.png +0 -0
  187. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-gold.png +0 -0
  188. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-green.png +0 -0
  189. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker.png +0 -0
  190. /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/robot.txt.tmpl +0 -0
  191. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/TM_EUROPE_BORDERS-0.3.sql +0 -0
  192. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arial.ttf +0 -0
  193. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbd.ttf +0 -0
  194. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbi.ttf +0 -0
  195. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Ariali.ttf +0 -0
  196. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Bold.ttf +0 -0
  197. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-BoldItalic.ttf +0 -0
  198. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Italic.ttf +0 -0
  199. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Regular.ttf +0 -0
  200. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdana.ttf +0 -0
  201. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanab.ttf +0 -0
  202. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanai.ttf +0 -0
  203. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanaz.ttf +0 -0
  204. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts.conf +0 -0
  205. /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/tinyows.xml.tmpl +0 -0
  206. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/legend.jrxml +0 -0
  207. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/logo.png +0 -0
  208. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/north.svg +0 -0
  209. /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/results.jrxml +0 -0
  210. /c2cgeoportal_geoportal/scaffolds/create/{pyproject.toml → {{cookiecutter.project}}/pyproject.toml} +0 -0
  211. /c2cgeoportal_geoportal/scaffolds/create/{run_alembic.sh → {{cookiecutter.project}}/run_alembic.sh} +0 -0
  212. {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.7.1.157.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  # Copyright (c) 2014-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
@@ -36,15 +34,16 @@ import re
36
34
  import shutil
37
35
  import subprocess
38
36
  import sys
39
- from argparse import ArgumentParser
37
+ from argparse import ArgumentParser, Namespace
38
+ from json.decoder import JSONDecodeError
40
39
  from subprocess import call, check_call, check_output
41
- from typing import Any, Dict, cast
40
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union, cast
42
41
 
43
42
  import pkg_resources
44
43
  import requests
45
44
  import yaml
46
45
 
47
- from c2cgeoportal_geoportal.lib.bashcolor import GREEN, RED, YELLOW, colorize
46
+ from c2cgeoportal_geoportal.lib.bashcolor import Color, colorize
48
47
 
49
48
  REQUIRED_TEMPLATE_KEYS = ["package", "srid", "extent"]
50
49
  TEMPLATE_EXAMPLE = {"package": "${package}", "srid": "${srid}", "extent": "489246, 78873, 837119, 296543"}
@@ -59,11 +58,44 @@ DIFF_NOTICE = (
59
58
  )
60
59
 
61
60
 
62
- def main():
63
- """
64
- tool used to do the application upgrade
65
- """
61
+ def fix_style() -> None:
62
+ """Fix the style of all the project files using isort, Black and Prettier."""
63
+
64
+ file_to_clean = []
65
+ for filename, content in (
66
+ (".prettierignore", "*.min.js\n"),
67
+ ("pyproject.toml", "[tool.black]\nline-length = 110\ntarget-version = ['py38']\n"),
68
+ (".prettierrc.yaml", "bracketSpacing: false\nquoteProps: preserve\n"),
69
+ (
70
+ ".editorconfig",
71
+ """root = true
72
+ [*]
73
+ max_line_length = 110
74
+ """,
75
+ ),
76
+ ):
77
+ if not os.path.exists(filename):
78
+ file_to_clean.append(filename)
79
+ if os.path.exists(os.path.join("CONST_create_template", filename)):
80
+ shutil.copyfile(os.path.join("CONST_create_template", filename), filename)
81
+ else:
82
+ with open(filename, "w", encoding="utf8") as file_:
83
+ file_.write(content)
84
+
85
+ if os.path.exists("ci/config.yaml"):
86
+ os.rename("ci/config.yaml", "ci/config.yaml_")
87
+ subprocess.run(["c2cciutils-checks", "--fix", "--check=isort"]) # pylint: disable=subprocess-run-check
88
+ subprocess.run(["c2cciutils-checks", "--fix", "--check=black"]) # pylint: disable=subprocess-run-check
89
+ subprocess.run(["c2cciutils-checks", "--fix", "--check=prettier"]) # pylint: disable=subprocess-run-check
90
+ if os.path.exists("ci/config.yaml_"):
91
+ os.rename("ci/config.yaml_", "ci/config.yaml")
92
+
93
+ for filename in file_to_clean:
94
+ os.remove(filename)
95
+
66
96
 
97
+ def main() -> None:
98
+ """Tool used to do the application upgrade."""
67
99
  parser = _fill_arguments()
68
100
  options = parser.parse_args()
69
101
 
@@ -71,7 +103,7 @@ def main():
71
103
  c2cupgradetool.upgrade()
72
104
 
73
105
 
74
- def _fill_arguments():
106
+ def _fill_arguments() -> ArgumentParser:
75
107
  parser = ArgumentParser()
76
108
  parser.add_argument(
77
109
  "--git-remote", metavar="GITREMOTE", help="Specify the remote branch", default="origin"
@@ -82,38 +114,40 @@ def _fill_arguments():
82
114
 
83
115
 
84
116
  class InteruptedException(Exception):
85
- pass
117
+ """The interrupted exception."""
86
118
 
87
119
 
88
120
  current_step_number = 0
89
121
 
90
122
 
91
123
  class Step:
92
- def __init__(self, step_number, file_marker=True):
124
+ """Decorator used for en upgrade step."""
125
+
126
+ def __init__(self, step_number: int, file_marker: bool = True):
93
127
  global current_step_number
94
128
  current_step_number = step_number
95
129
  self.step_number = step_number
96
130
  self.file_marker = file_marker
97
131
 
98
- def __call__(self, current_step):
99
- def decorate(c2cupgradetool, *args, **kwargs):
132
+ def __call__(
133
+ self, current_step: Callable[["C2cUpgradeTool", int], None]
134
+ ) -> Callable[["C2cUpgradeTool"], None]:
135
+ def decorate(c2cupgradetool: "C2cUpgradeTool") -> None:
100
136
  try:
101
- if os.path.isfile(".UPGRADE{}".format(self.step_number - 1)):
102
- os.unlink(".UPGRADE{}".format(self.step_number - 1))
137
+ if os.path.isfile(f".UPGRADE{self.step_number - 1}"):
138
+ os.unlink(f".UPGRADE{self.step_number - 1}")
103
139
  if self.file_marker:
104
- with open(".UPGRADE{}".format(self.step_number), "w"):
140
+ with open(f".UPGRADE{self.step_number}", "w", encoding="utf8"):
105
141
  pass
106
- print("Start step {}.".format(self.step_number))
142
+ print(f"Start step {self.step_number}.")
107
143
  sys.stdout.flush()
108
- current_step(c2cupgradetool, self.step_number, *args, **kwargs)
144
+ current_step(c2cupgradetool, self.step_number)
109
145
  except subprocess.CalledProcessError as exception:
146
+ command = " ".join([f"'{exception}'" for exception in exception.cmd])
110
147
  c2cupgradetool.print_step(
111
148
  self.step_number,
112
149
  error=True,
113
- message="The command `{}` returns the error code {}.".format(
114
- " ".join(["'{}'".format(exception) for exception in exception.cmd]),
115
- exception.returncode,
116
- ),
150
+ message=f"The command `{command}` returns the error code {exception.returncode}.",
117
151
  prompt="Fix the error and run the step again:",
118
152
  )
119
153
  sys.exit(1)
@@ -121,21 +155,20 @@ class Step:
121
155
  c2cupgradetool.print_step(
122
156
  self.step_number,
123
157
  error=True,
124
- message="There was an error: {}.".format(exception),
158
+ message=f"There was an error: {exception}.",
125
159
  prompt="Fix the error and run the step again:",
126
160
  )
127
161
  sys.exit(1)
128
162
  except Exception as exception:
129
- cautch_exception = exception
163
+ catch_exception = exception
130
164
 
131
- global current_step_number
132
165
  if self.step_number == current_step_number:
133
166
 
134
- def message():
167
+ def message() -> None:
135
168
  c2cupgradetool.print_step(
136
169
  self.step_number,
137
170
  error=True,
138
- message="The step had the error '{}'.".format(cautch_exception),
171
+ message=f"The step had the error '{catch_exception}'.",
139
172
  prompt="Fix the error and run the step again:",
140
173
  )
141
174
 
@@ -146,84 +179,101 @@ class Step:
146
179
 
147
180
 
148
181
  class C2cUpgradeTool:
182
+ """The tool used to upgrade the application."""
149
183
 
150
- color_bar = colorize("================================================================", GREEN)
184
+ color_bar = colorize("================================================================", Color.GREEN)
151
185
 
152
- def __init__(self, options):
186
+ def __init__(self, options: Namespace):
153
187
  self.options = options
154
- self.project: Dict[str, Any] = self.get_project()
188
+ self.project = self.get_project()
155
189
 
156
190
  @staticmethod
157
- def get_project():
191
+ def get_project() -> Dict[str, Any]:
158
192
  if not os.path.isfile("project.yaml"):
159
- print(colorize("Unable to find the required 'project.yaml' file.", RED))
193
+ print(colorize("Unable to find the required 'project.yaml' file.", Color.RED))
160
194
  sys.exit(1)
161
195
 
162
- with open("project.yaml", "r") as project_file:
163
- return yaml.safe_load(project_file)
196
+ with open("project.yaml", encoding="utf8") as project_file:
197
+ return cast(Dict[str, Any], yaml.safe_load(project_file))
164
198
 
165
199
  @staticmethod
166
- def get_upgrade(section):
200
+ def get_upgrade(section: str) -> Union[List[Any], Dict[str, Any]]:
167
201
  if not os.path.isfile(".upgrade.yaml"):
168
- print(colorize("Unable to find the required '.upgrade.yaml' file.", RED))
202
+ print(colorize("Unable to find the required '.upgrade.yaml' file.", Color.RED))
169
203
  sys.exit(1)
170
204
 
171
- with open(".upgrade.yaml", "r") as project_file:
172
- return yaml.safe_load(project_file)[section]
173
-
174
- def print_step(self, step, error=False, message=None, prompt="To continue, type:"):
175
- with open(".UPGRADE_INSTRUCTIONS", "w") as instructions:
205
+ with open(".upgrade.yaml", encoding="utf8") as project_file:
206
+ return cast(Union[List[Any], Dict[str, Any]], yaml.safe_load(project_file)[section])
207
+
208
+ def print_step(
209
+ self,
210
+ step: int,
211
+ error: bool = False,
212
+ message: Optional[str] = None,
213
+ prompt: str = "To continue, type:",
214
+ ) -> None:
215
+ with open(".UPGRADE_INSTRUCTIONS", "w", encoding="utf8") as instructions:
176
216
  print("")
177
217
  print(self.color_bar)
178
218
  if message is not None:
179
- print(colorize(message, RED if error else YELLOW))
180
- instructions.write("{}\n".format(message))
219
+ print(colorize(message, Color.RED if error else Color.YELLOW))
220
+ instructions.write(f"{message}\n")
181
221
  if step >= 0:
182
- print(colorize(prompt, GREEN))
183
- instructions.write("{}\n".format(prompt))
222
+ print(colorize(prompt, Color.GREEN))
223
+ instructions.write(f"{prompt}\n")
184
224
  cmd = ["./upgrade", os.environ["VERSION"]]
185
225
  if step != 0:
186
- cmd.append("{}".format(step))
187
- print(colorize(" ".join(cmd), GREEN))
188
- instructions.write("{}\n".format(" ".join(cmd)))
226
+ cmd.append(f"{step}")
227
+ print(colorize(" ".join(cmd), Color.GREEN))
228
+ instructions.write(f"{' '.join(cmd)}\n")
189
229
 
190
- def run_step(self, step):
191
- getattr(self, "step{}".format(step))()
230
+ def run_step(self, step: int) -> None:
231
+ getattr(self, f"step{step}")()
192
232
 
193
- def test_checkers(self):
194
- run_curl = "Run `curl --insecure {} '{}'` for more information.".format(
195
- " ".join(["--header {}={}".format(*i) for i in self.project.get("checker_headers", {}).items()]),
196
- self.project["checker_url"],
233
+ def test_checkers(self) -> Tuple[bool, Optional[str]]:
234
+ headers = " ".join(
235
+ [f"--header {i[0]}={i[1]}" for i in self.project.get("checker_headers", {}).items()]
197
236
  )
237
+ run_curl = f"Run `curl --insecure {headers} '{self.project['checker_url']}'` for more information."
198
238
  try:
199
- requests.packages.urllib3.disable_warnings()
239
+ requests.packages.urllib3.disable_warnings() # type: ignore
200
240
  resp = requests.get(
201
- self.project["checker_url"], headers=self.project.get("checker_headers"), verify=False
241
+ self.project["checker_url"],
242
+ headers=self.project.get("checker_headers"),
243
+ verify=False, # nosec
202
244
  )
203
245
  except requests.exceptions.ConnectionError as exception:
204
- return False, "\n".join(["Connection error: {}".format(exception), run_curl])
246
+ return False, "\n".join([f"Connection error: {exception}", run_curl])
205
247
  except ConnectionRefusedError as exception:
206
- return False, "\n".join(["Connection refused: {}".format(exception), run_curl])
248
+ return False, "\n".join([f"Connection refused: {exception}", run_curl])
207
249
  if resp.status_code < 200 or resp.status_code >= 300:
208
250
 
209
- print(colorize("=============", RED))
210
- print(colorize("Checker error", RED))
211
- for name, value in resp.json()["failures"].items():
212
- print(colorize("Test '{}' failed with result:".format(name), YELLOW))
213
- del value["level"]
214
- del value["timing"]
215
-
216
- print(yaml.dump(value) if value != {} else "No result")
251
+ print(colorize("=============", Color.RED))
252
+ print(colorize("Checker error", Color.RED))
253
+ try:
254
+ for name, value in resp.json()["failures"].items():
255
+ print(colorize(f"Test '{name}' failed with result:", Color.YELLOW))
256
+ del value["level"]
257
+ del value["timing"]
258
+
259
+ print(yaml.dump(value) if value != {} else "No result")
260
+ except JSONDecodeError:
261
+ print(
262
+ colorize(
263
+ f"Response is not a JSON '{resp.text}', {resp.reason} {resp.status_code}",
264
+ Color.RED,
265
+ )
266
+ )
217
267
 
218
268
  return False, "\n".join(["Checker error:", run_curl])
219
269
 
220
270
  return True, None
221
271
 
222
- def upgrade(self):
272
+ def upgrade(self) -> None:
223
273
  self.run_step(self.options.step)
224
274
 
225
275
  @Step(0, file_marker=False)
226
- def step0(self, step):
276
+ def step0(self, step: int) -> None:
227
277
  project_template_keys = list(cast(Dict[str, Any], self.project.get("template_vars")).keys())
228
278
  messages = []
229
279
  for required in REQUIRED_TEMPLATE_KEYS:
@@ -255,11 +305,11 @@ class C2cUpgradeTool:
255
305
  message="Here is the output of 'git status'. Please make sure to commit all your "
256
306
  "changes before going further. All uncommitted changes will be lost.\n"
257
307
  "Note that for debugging purpose it is possible to pass directly to step 2 "
258
- "e.-g.: ./upgrade --debug=../c2cgeoportal {version} 2".format(version=os.environ["VERSION"]),
308
+ f"e.-g.: ./upgrade --debug=../c2cgeoportal {os.environ['VERSION']} 2",
259
309
  )
260
310
 
261
311
  @Step(1)
262
- def step1(self, step):
312
+ def step1(self, step: int) -> None:
263
313
  shutil.copyfile("project.yaml", "/tmp/project.yaml")
264
314
  try:
265
315
  check_call(["git", "reset", "--hard"])
@@ -270,75 +320,38 @@ class C2cUpgradeTool:
270
320
  self.run_step(step + 1)
271
321
 
272
322
  @Step(2)
273
- def step2(self, step):
274
- with open(".eslintrc", "w") as eslintrc_file:
275
- eslintrc_file.write(
276
- """extends:
277
- - openlayers
278
- globals:
279
- '{}': false
280
- env:
281
- jquery: true
282
- parserOptions:
283
- ecmaVersion: 2017
284
- rules:
285
- no-console: 0
286
- comma-dangle: 0
287
- import/no-unresolved: 0
288
- valid-jsdoc: 0
289
- sort-imports-es6-autofix/sort-imports-es6: 0
290
- prettier/prettier: 1
291
- """.format(
292
- self.project["project_package"]
293
- )
294
- )
295
-
296
- app_js_files = []
297
- for base in ("CONST_create_template/", ""):
298
- try:
299
- app_js_files.extend(
300
- check_output(
301
- [
302
- "find",
303
- base + self.project["project_package"] + "_geoportal/static-ngeo/js",
304
- "-type",
305
- "f",
306
- "-name",
307
- "*.js",
308
- ]
309
- )
310
- .decode()
311
- .split()
312
- )
313
- except Exception:
314
- pass
315
-
316
- if app_js_files:
317
- call(["eslint", "--fix"] + app_js_files)
318
-
319
- os.remove(".eslintrc")
320
- check_call(["git", "add"] + app_js_files)
321
- call(["git", "commit", "--message=Run code style"])
323
+ def step2(self, step: int) -> None:
324
+ fix_style()
325
+ subprocess.run(["git", "add", "-A"]) # pylint: disable=subprocess-run-check
326
+ subprocess.run(["git", "commit", "--message=Run code style"]) # pylint: disable=subprocess-run-check
322
327
 
323
328
  self.run_step(step + 1)
324
329
 
325
330
  @Step(3)
326
- def step3(self, step):
331
+ def step3(self, step: int) -> None:
327
332
  project_path = os.path.join("/tmp", self.project["project_folder"])
328
333
  os.mkdir(project_path)
329
334
  shutil.copyfile("/src/project.yaml", os.path.join(project_path, "project.yaml"))
330
335
  check_call(
331
336
  [
332
337
  "pcreate",
333
- "--ignore-conflicting-name",
334
338
  "--overwrite",
335
- "--scaffold=c2cgeoportal_update",
339
+ "--scaffold=update",
336
340
  project_path,
337
341
  ]
338
342
  )
343
+ if self.get_project().get("advance", False):
344
+ check_call(
345
+ [
346
+ "pcreate",
347
+ "--overwrite",
348
+ "--scaffold=advance_update",
349
+ project_path,
350
+ ]
351
+ )
339
352
 
340
353
  shutil.copyfile(os.path.join(project_path, ".upgrade.yaml"), ".upgrade.yaml")
341
- for upgrade_file in self.get_upgrade("upgrade_files"):
354
+ for upgrade_file in cast(List[Dict[str, Any]], self.get_upgrade("upgrade_files")):
342
355
  action = upgrade_file["action"]
343
356
  if action == "remove":
344
357
  self.files_to_remove(upgrade_file, prefix="CONST_create_template", force=True)
@@ -354,7 +367,7 @@ rules:
354
367
  self.run_step(step + 1)
355
368
 
356
369
  @Step(4)
357
- def step4(self, step):
370
+ def step4(self, step: int) -> None:
358
371
  if os.path.exists("CONST_create_template"):
359
372
  check_call(["git", "rm", "-r", "--force", "CONST_create_template/"])
360
373
 
@@ -363,37 +376,79 @@ rules:
363
376
  check_call(
364
377
  [
365
378
  "pcreate",
366
- "--ignore-conflicting-name",
367
379
  "--overwrite",
368
- "--scaffold=c2cgeoportal_update",
380
+ "--scaffold=update",
369
381
  project_path,
370
382
  ]
371
383
  )
384
+ if self.get_project().get("advance", False):
385
+ check_call(
386
+ [
387
+ "pcreate",
388
+ "--overwrite",
389
+ "--scaffold=advance_update",
390
+ project_path,
391
+ ]
392
+ )
372
393
  os.remove(project_path)
373
394
 
395
+ check_call(["git", "add", "--all", "CONST_create_template/"])
396
+
397
+ def changed_files() -> List[str]:
398
+ try:
399
+ status = [
400
+ [s for s in status.strip().split(" ", maxsplit=1) if s]
401
+ for status in check_git_status_output().strip().split("\n")
402
+ if status
403
+ ]
404
+ return [
405
+ file.strip().split(" ")[-1]
406
+ for state, file in status
407
+ if state == "M" and not file.strip().startswith("CONST_")
408
+ ]
409
+ except: # pylint: disable=bare-except
410
+ self.print_step(
411
+ step,
412
+ error=True,
413
+ message=f"Error while getting changed files:\n{check_git_status_output()}",
414
+ prompt="Fix the error and run the step again:",
415
+ )
416
+ sys.exit(1)
417
+
418
+ changed_before_style = changed_files()
419
+
420
+ fix_style()
421
+
422
+ # Revert code style changes in the project otherwise we get an error: does not match index
423
+ # on git apply.
424
+ changed_after_style = changed_files()
425
+ to_checkout = [file for file in changed_after_style if file not in changed_before_style]
426
+ if to_checkout:
427
+ subprocess.run(["git", "checkout"] + to_checkout, check=True)
428
+
374
429
  check_call(["git", "add", "--all", "CONST_create_template/"])
375
430
  check_call(["git", "clean", "-Xf", "CONST_create_template/"])
376
431
  self.run_step(step + 1)
377
432
 
378
433
  @Step(5)
379
- def step5(self, step):
434
+ def step5(self, step: int) -> None:
380
435
  if "managed_files" not in self.project:
436
+ unmanaged_files = "\n".join(["- " + e for e in self.project.get("unmanaged_files", [])])
381
437
  self.print_step(
382
438
  step,
383
- message="In the new version, we will also manage almost all the create "
384
- "template files.\n"
385
- "By default, files conforming to the following regex pattern will not be replaced:\n{}"
386
- "Therefore, you should fill the 'managed_files' in you 'project.yaml' file with at least "
387
- "`[]`.".format("\n".join(["- " + e for e in self.project.get("unmanaged_files", [])])),
439
+ message="In the new version, we will also manage almost all the create template files.\n"
440
+ "By default, files conforming to the following regex pattern will not be replaced:\n"
441
+ f"{unmanaged_files} Therefore, you should fill the 'managed_files' in you 'project.yaml' "
442
+ "file with at least `[]`.",
388
443
  prompt="Fill it and run the step again:",
389
444
  )
390
445
  else:
391
446
  self.run_step(step + 1)
392
447
 
393
448
  @Step(6)
394
- def step6(self, step):
449
+ def step6(self, step: int) -> None:
395
450
  task_to_do = False
396
- for upgrade_file in self.get_upgrade("upgrade_files"):
451
+ for upgrade_file in cast(List[Dict[str, Any]], self.get_upgrade("upgrade_files")):
397
452
  action = upgrade_file["action"]
398
453
  if action == "remove":
399
454
  task_to_do |= self.files_to_remove(upgrade_file)
@@ -415,7 +470,7 @@ rules:
415
470
  else:
416
471
  self.run_step(step + 1)
417
472
 
418
- def files_to_remove(self, element, prefix="", force=False):
473
+ def files_to_remove(self, element: Dict[str, Any], prefix: str = "", force: bool = False) -> bool:
419
474
  task_to_do = False
420
475
  for path in element["paths"]:
421
476
  file_ = os.path.join(prefix, path.format(package=self.project["project_package"]))
@@ -433,31 +488,30 @@ rules:
433
488
  if no_touch:
434
489
  managed = True
435
490
  else:
436
- # fmt: off
437
- print(colorize(
438
- "The file '{}' has been removed but he is in the `managed_files` as '{}'."
439
- .format(file_, pattern),
440
- RED
441
- ))
442
- # fmt: on
491
+ print(
492
+ colorize(
493
+ f"The file '{file_}' has been removed but he is in the "
494
+ f"`managed_files` as '{pattern}'.",
495
+ Color.RED,
496
+ )
497
+ )
443
498
  task_to_do = True
444
499
  for pattern in self.project.get("unmanaged_files", []):
445
500
  if re.match(pattern + "$", file_):
446
- # fmt: off
447
- print(colorize(
448
- "The file '{}' has been removed but he is in the `unmanaged_files` as '{}'."
449
- .format(file_, pattern),
450
- YELLOW
451
- ))
452
- # fmt: on
501
+ print(
502
+ colorize(
503
+ f"The file '{file_}' has been removed but he is in the "
504
+ f"`unmanaged_files` as '{pattern}'.",
505
+ Color.YELLOW,
506
+ )
507
+ )
453
508
  task_to_do = True
454
509
  if not managed:
455
- print("The file '{}' is removed.".format(file_))
510
+ print(f"The file '{file_}' is removed.")
456
511
  if "version" in element and "from" in element:
457
512
  print(
458
- "Was used in version {}, to be removed from version {}.".format(
459
- element["from"], element["version"]
460
- )
513
+ f"Was used in version {element['from']}, to be removed from version "
514
+ f"{element['version']}."
461
515
  )
462
516
  if os.path.isdir(file_):
463
517
  shutil.rmtree(file_)
@@ -465,7 +519,7 @@ rules:
465
519
  os.remove(file_)
466
520
  return task_to_do
467
521
 
468
- def files_to_move(self, element, prefix="", force=False):
522
+ def files_to_move(self, element: Dict[str, Any], prefix: str = "", force: bool = False) -> bool:
469
523
  task_to_do = False
470
524
  src = os.path.join(prefix, element["from"].format(package=self.project["project_package"]))
471
525
  dst = os.path.join(prefix, element["to"].format(package=self.project["project_package"]))
@@ -486,20 +540,18 @@ rules:
486
540
  else:
487
541
  print(
488
542
  colorize(
489
- "The {} '{}' is present in the `managed_files` as '{}', "
490
- "but it has been moved to '{}'.".format(type_, src, pattern, dst),
491
- RED,
543
+ f"The {type_} '{src}' is present in the `managed_files` as '{pattern}', "
544
+ f"but it has been moved to '{dst}'.",
545
+ Color.RED,
492
546
  )
493
547
  )
494
548
  task_to_do = True
495
549
  if re.match(pattern + "$", dst):
496
550
  print(
497
551
  colorize(
498
- "The {} '{}' is present in the `managed_files` as '{}', "
499
- "but a file have been moved on it from '{}'.".format(
500
- type_, dst, pattern, src
501
- ),
502
- RED,
552
+ f"The {type_} '{dst}' is present in the `managed_files` as '{pattern}', "
553
+ f"but a file have been moved on it from '{src}'.",
554
+ Color.RED,
503
555
  )
504
556
  )
505
557
  task_to_do = True
@@ -507,45 +559,46 @@ rules:
507
559
  if re.match(pattern + "$", src):
508
560
  print(
509
561
  colorize(
510
- "The {} '{}' is present in the `unmanaged_files` as '{}', "
511
- "but it has been moved to '{}'.".format(type_, src, pattern, dst),
512
- YELLOW,
562
+ f"The {type_} '{src}' is present in the `unmanaged_files` as '{pattern}', "
563
+ f"but it has been moved to '{dst}'.",
564
+ Color.YELLOW,
513
565
  )
514
566
  )
515
567
  task_to_do = True
516
568
  if re.match(pattern + "$", dst):
517
569
  print(
518
570
  colorize(
519
- "The {} '{}' is present in the `unmanaged_files` as '{}', "
520
- "but a file have been moved on it from '{}'.".format(
521
- type_, dst, pattern, src
522
- ),
523
- YELLOW,
571
+ f"The {type_} '{dst}' is present in the `unmanaged_files` as '{pattern}', "
572
+ f"but a file have been moved on it from '{src}'.",
573
+ Color.YELLOW,
524
574
  )
525
575
  )
526
576
  task_to_do = True
527
577
  if not managed and os.path.exists(dst) and not element.get("override", False):
528
- print(colorize("The destination '{}' already exists, ignoring.".format(dst), YELLOW))
578
+ print(colorize(f"The destination '{dst}' already exists, ignoring.", Color.YELLOW))
529
579
  elif not managed:
530
- print("Move the {} '{}' to '{}'.".format(type_, src, dst))
580
+ print(f"Move the {type_} '{src}' to '{dst}'.")
531
581
  if "version" in element:
532
- print("Needed from version {}.".format(element["version"]))
582
+ print(f"Needed from version {element['version']}.")
533
583
  if os.path.dirname(dst) != "":
534
584
  os.makedirs(os.path.dirname(dst), exist_ok=True)
535
585
  try:
536
586
  check_call(["git", "mv", src, dst])
537
587
  except Exception as exception:
538
- print("[Warning] Git move error: {}.".format(exception))
588
+ print(f"[Warning] Git move error: {exception}.")
539
589
  os.rename(src, dst)
540
590
  return task_to_do
541
591
 
542
592
  @Step(7)
543
- def step7(self, step):
593
+ def step7(self, step: int) -> None:
544
594
  self.files_to_get(step)
545
595
  self.run_step(step + 1)
546
596
 
547
- def is_managed(self, file_, files_to_get=False):
548
- default_project_file = self.get_upgrade("default_project_file")
597
+ def is_managed(self, file_: str, files_to_get: bool = False) -> bool:
598
+ # Dictionary with:
599
+ # include: list of include regular expression
600
+ # exclude: list of exclude regular expression
601
+ default_project_file = cast(Dict[str, List[str]], self.get_upgrade("default_project_file"))
549
602
 
550
603
  # Managed means managed by the application owner, not the c2cupgrade
551
604
  managed = False
@@ -556,23 +609,23 @@ rules:
556
609
  ):
557
610
  for pattern in default_project_file["include"]:
558
611
  if re.match(pattern + "$", file_):
559
- print("File '{}' included by migration config pattern '{}'.".format(file_, pattern))
612
+ print(f"File '{file_}' included by migration config pattern '{pattern}'.")
560
613
  managed = True
561
614
  break
562
615
  if managed:
563
616
  for pattern in default_project_file["exclude"]:
564
617
  if re.match(pattern + "$", file_):
565
- print("File '{}' excluded by migration config pattern '{}'.".format(file_, pattern))
618
+ print(f"File '{file_}' excluded by migration config pattern '{pattern}'.")
566
619
  print("managed", file_, pattern)
567
620
  managed = False
568
621
  break
569
622
  else:
570
- print("New file '{}'.".format(file_))
623
+ print(f"New file '{file_}'.")
571
624
 
572
625
  if not managed and not os.path.exists(file_):
573
626
  for pattern in self.get_upgrade("extra"):
574
627
  if re.match(pattern + "$", file_):
575
- print("File '{}' is an extra by migration config pattern '{}'.".format(file_, pattern))
628
+ print(f"File '{file_}' is an extra by migration config pattern '{pattern}'.")
576
629
  managed = True
577
630
 
578
631
  if not managed:
@@ -582,39 +635,29 @@ rules:
582
635
  else:
583
636
  pattern = files["pattern"]
584
637
  if re.match(pattern + "$", file_):
585
- print(
586
- "File '{}' included by project config pattern `managed_files` '{}'.".format(
587
- file_, pattern
588
- )
589
- )
638
+ print(f"File '{file_}' included by project config pattern `managed_files` '{pattern}'.")
590
639
  print("managed", file_, pattern)
591
640
  managed = True
592
641
  break
593
642
  if managed:
594
643
  for pattern in self.project.get("unmanaged_files", []):
595
644
  if re.match(pattern + "$", file_):
596
- print(
597
- "File '{}' excluded by project config pattern `unmanaged_files` '{}'.".format(
598
- file_, pattern
599
- )
600
- )
645
+ print(f"File '{file_}' excluded by project config pattern `unmanaged_files` '{pattern}'.")
601
646
  managed = False
602
647
  break
603
648
 
604
649
  return managed
605
650
 
606
- def files_to_get(self, step, pre=False):
651
+ def files_to_get(self, step: int, pre: bool = False) -> bool:
607
652
  error = False
608
653
  for root, _, files in os.walk("CONST_create_template"):
609
- # fmt: off
610
- root = root[len("CONST_create_template/"):]
611
- # fmt: on
654
+ root = root[len("CONST_create_template/") :]
612
655
  for file_ in files:
613
656
  destination = os.path.join(root, file_)
614
657
  managed = self.is_managed(destination, True)
615
658
  source = os.path.join("CONST_create_template", destination)
616
659
  if not managed and (not os.path.exists(destination) or not filecmp.cmp(source, destination)):
617
- print(colorize("Get the file '{}' from the create template.".format(destination), GREEN))
660
+ print(colorize(f"Get the file '{destination}' from the create template.", Color.GREEN))
618
661
  if not pre:
619
662
  if os.path.dirname(destination) != "":
620
663
  os.makedirs(os.path.dirname(destination), exist_ok=True)
@@ -633,17 +676,17 @@ rules:
633
676
  )
634
677
  sys.exit(1)
635
678
  elif managed:
636
- print("The file '{}' is managed by the project.".format(destination))
679
+ print(f"The file '{destination}' is managed by the project.")
637
680
  elif os.path.exists(destination) and filecmp.cmp(source, destination):
638
- print("The file '{}' does not change.".format(destination))
681
+ print(f"The file '{destination}' does not change.")
639
682
  else:
640
- print("Unknown stat for the file '{}'.".format(destination))
683
+ print(f"Unknown stat for the file '{destination}'.")
641
684
  sys.exit(2)
642
685
  return error
643
686
 
644
687
  @Step(8)
645
- def step8(self, step):
646
- with open("changelog.diff", "w") as diff_file:
688
+ def step8(self, step: int) -> None:
689
+ with open("changelog.diff", "w", encoding="utf8") as diff_file:
647
690
  check_call(["git", "diff", "--", "CONST_CHANGELOG.txt"], stdout=diff_file)
648
691
 
649
692
  from210 = False
@@ -664,30 +707,28 @@ rules:
664
707
  "file (listed in the `changelog.diff` file).",
665
708
  )
666
709
 
667
- def get_modified(self, status_path):
668
- status = check_git_status_output([status_path])
669
- status = [s for s in status.split("\n") if len(s) > 3]
710
+ def get_modified(self, status_path: str) -> List[str]:
711
+ status = check_git_status_output([status_path]).split("\n")
712
+ status = [s for s in status if len(s) > 3]
670
713
  status = [s[3:] for s in status if s[:3].strip() == "M"]
671
714
  for pattern in self.get_upgrade("no_diff"):
672
- matcher = re.compile("CONST_create_template/{}$".format(pattern))
715
+ matcher = re.compile(f"CONST_create_template/{pattern}$")
673
716
  status = [s for s in status if not matcher.match(s)]
674
- # fmt: off
675
- status = [s for s in status if os.path.exists(s[len("CONST_create_template/"):])]
676
- status = [s for s in status if not filecmp.cmp(s, s[len("CONST_create_template/"):])]
677
- # fmt: on
717
+ status = [s for s in status if os.path.exists(s[len("CONST_create_template/") :])]
718
+ status = [s for s in status if not filecmp.cmp(s, s[len("CONST_create_template/") :])]
678
719
  return status
679
720
 
680
721
  @Step(9)
681
- def step9(self, step):
722
+ def step9(self, step: int) -> None:
682
723
  if os.path.isfile("changelog.diff"):
683
724
  os.unlink("changelog.diff")
684
725
 
685
726
  status = self.get_modified(
686
- "CONST_create_template/geoportal/{}_geoportal/static-ngeo".format(self.project["project_package"])
727
+ f"CONST_create_template/geoportal/{self.project['project_package']}_geoportal/static-ngeo"
687
728
  )
688
729
  status += ["CONST_create_template/geoportal/vars.yaml"]
689
730
 
690
- with open("ngeo.diff", "w") as diff_file:
731
+ with open("ngeo.diff", "w", encoding="utf8") as diff_file:
691
732
  if status:
692
733
  check_call(
693
734
  ["git", "diff", "--relative=CONST_create_template", "--staged", "--"] + status,
@@ -705,7 +746,7 @@ rules:
705
746
  )
706
747
 
707
748
  @Step(10)
708
- def step10(self, step):
749
+ def step10(self, step: int) -> None:
709
750
  if os.path.isfile("ngeo.diff"):
710
751
  os.unlink("ngeo.diff")
711
752
 
@@ -714,15 +755,13 @@ rules:
714
755
  s
715
756
  for s in status
716
757
  if not s.startswith(
717
- "CONST_create_template/geoportal/{}_geoportal/static-ngeo/".format(
718
- self.project["project_package"]
719
- )
758
+ f"CONST_create_template/geoportal/{self.project['project_package']}_geoportal/static-ngeo/"
720
759
  )
721
760
  ]
722
761
  status = [s for s in status if s != "CONST_create_template/geoportal/vars.yaml"]
723
762
 
724
763
  if status:
725
- with open("create.diff", "w") as diff_file:
764
+ with open("create.diff", "w", encoding="utf8") as diff_file:
726
765
  if status:
727
766
  check_call(
728
767
  ["git", "diff", "--relative=CONST_create_template", "--staged", "--"] + status,
@@ -743,24 +782,24 @@ rules:
743
782
  self.run_step(step + 1)
744
783
 
745
784
  @Step(11)
746
- def step11(self, step):
785
+ def step11(self, step: int) -> None:
747
786
  if os.path.isfile("create.diff"):
748
787
  os.unlink("create.diff")
749
788
 
750
789
  message = [
751
790
  "The upgrade is nearly done, now you should:",
752
791
  "- Build your application with `./upgrade --finalize [build arguments]`",
753
- "- Test your application on '{}'.".format(self.project.get("application_url", "... missing ...")),
792
+ f"- Test your application on '{self.project.get('application_url', '... missing ...')}'.",
754
793
  ]
755
794
 
756
795
  if os.path.isfile(".upgrade.yaml"):
757
796
  os.unlink(".upgrade.yaml")
758
- with open(".UPGRADE_SUCCESS", "w"):
797
+ with open(".UPGRADE_SUCCESS", "w", encoding="utf8"):
759
798
  pass
760
799
  self.print_step(step + 1, message="\n".join(message))
761
800
 
762
801
  @Step(12, file_marker=False)
763
- def step12(self, step):
802
+ def step12(self, step: int) -> None:
764
803
  if os.path.isfile(".UPGRADE_SUCCESS"):
765
804
  os.unlink(".UPGRADE_SUCCESS")
766
805
  good, message = self.test_checkers()
@@ -772,12 +811,12 @@ rules:
772
811
  error=True,
773
812
  message=message,
774
813
  prompt="Correct the checker, then run the step again "
775
- "(If you want to fix it later you can pass to the next step):",
814
+ "(If you want to fix it later you can pass to the next step:int):",
776
815
  )
777
816
  sys.exit(1)
778
817
 
779
818
  @Step(13, file_marker=False)
780
- def step13(self, step):
819
+ def step13(self, step: int) -> None:
781
820
  # Required to remove from the Git stage the ignored file when we lunch the step again
782
821
  check_call(["git", "reset", "--mixed"])
783
822
 
@@ -788,35 +827,35 @@ rules:
788
827
  step + 1,
789
828
  message="We will commit all the above files!\n"
790
829
  "If there are some files which should not be committed, then you should "
791
- "add them into the `.gitignore` file and launch upgrade {} again.".format(step),
830
+ f"add them into the `.gitignore` file and launch upgrade {step} again.",
792
831
  prompt="Then to commit your changes type:",
793
832
  )
794
833
 
795
834
  @Step(14, file_marker=False)
796
- def step14(self, _):
835
+ def step14(self, _: int) -> None:
797
836
  if os.path.isfile(".UPGRADE_INSTRUCTIONS"):
798
837
  os.unlink(".UPGRADE_INSTRUCTIONS")
799
838
  check_call(
800
839
  [
801
840
  "git",
802
841
  "commit",
803
- "--message=Upgrade to GeoMapFish {}".format(
804
- pkg_resources.get_distribution("c2cgeoportal_commons").version
805
- ),
842
+ "--message=Upgrade to GeoMapFish "
843
+ f"{pkg_resources.get_distribution('c2cgeoportal_commons').version}",
806
844
  ]
807
845
  )
808
846
 
809
847
  print("")
810
848
  print(self.color_bar)
811
849
  print("")
812
- print(colorize("Congratulations, your upgrade was successful.", GREEN))
850
+ print(colorize("Congratulations, your upgrade was successful.", Color.GREEN))
813
851
  print("")
814
852
  branch = check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).decode("utf-8").strip()
815
853
  print("Now all your files are committed; you should do a git push:")
816
- print("git push {0!s} {1!s}.".format(self.options.git_remote, branch))
854
+ print(f"git push {self.options.git_remote} {branch}.")
817
855
 
818
856
 
819
- def check_git_status_output(args=None):
857
+ def check_git_status_output(args: Optional[List[str]] = None) -> str:
858
+ """Check if there is something that's not committed."""
820
859
  return check_output(["git", "status", "--short"] + (args if args is not None else [])).decode("utf-8")
821
860
 
822
861