c2cgeoportal-geoportal 2.3.5.79__py3-none-any.whl → 2.9rc44__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. c2cgeoportal_geoportal/__init__.py +960 -0
  2. c2cgeoportal_geoportal/lib/__init__.py +256 -0
  3. c2cgeoportal_geoportal/lib/authentication.py +250 -0
  4. c2cgeoportal_geoportal/lib/bashcolor.py +46 -0
  5. c2cgeoportal_geoportal/lib/cacheversion.py +77 -0
  6. c2cgeoportal_geoportal/lib/caching.py +176 -0
  7. c2cgeoportal_geoportal/lib/check_collector.py +80 -0
  8. c2cgeoportal_geoportal/lib/checker.py +295 -0
  9. c2cgeoportal_geoportal/lib/common_headers.py +172 -0
  10. c2cgeoportal_geoportal/lib/dbreflection.py +266 -0
  11. c2cgeoportal_geoportal/lib/filter_capabilities.py +360 -0
  12. c2cgeoportal_geoportal/lib/fulltextsearch.py +50 -0
  13. c2cgeoportal_geoportal/lib/functionality.py +166 -0
  14. c2cgeoportal_geoportal/lib/headers.py +62 -0
  15. c2cgeoportal_geoportal/lib/i18n.py +38 -0
  16. c2cgeoportal_geoportal/lib/layers.py +132 -0
  17. c2cgeoportal_geoportal/lib/lingva_extractor.py +937 -0
  18. c2cgeoportal_geoportal/lib/loader.py +57 -0
  19. c2cgeoportal_geoportal/lib/metrics.py +117 -0
  20. c2cgeoportal_geoportal/lib/oauth2.py +1186 -0
  21. c2cgeoportal_geoportal/lib/oidc.py +304 -0
  22. c2cgeoportal_geoportal/lib/wmstparsing.py +353 -0
  23. c2cgeoportal_geoportal/lib/xsd.py +166 -0
  24. c2cgeoportal_geoportal/py.typed +0 -0
  25. c2cgeoportal_geoportal/resources.py +49 -0
  26. c2cgeoportal_geoportal/scaffolds/advance_create/ci/config.yaml +26 -0
  27. c2cgeoportal_geoportal/scaffolds/advance_create/cookiecutter.json +18 -0
  28. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.dockerignore +6 -0
  29. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.eslintrc.yaml +19 -0
  30. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.prospector.yaml +30 -0
  31. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/Dockerfile +75 -0
  32. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/Makefile +6 -0
  33. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/alembic.ini +58 -0
  34. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/alembic.yaml +19 -0
  35. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/development.ini +121 -0
  36. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +139 -0
  37. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/language_mapping +3 -0
  38. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/lingva-client.cfg +5 -0
  39. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/lingva-server.cfg +6 -0
  40. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/production.ini +38 -0
  41. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +2 -0
  42. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/setup.py +25 -0
  43. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +41 -0
  44. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js +64 -0
  45. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.commons.js +11 -0
  46. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.config.js +22 -0
  47. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +42 -0
  48. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/authentication.py +10 -0
  49. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/dev.py +14 -0
  50. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/models.py +8 -0
  51. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/multi_organization.py +7 -0
  52. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/resources.py +11 -0
  53. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/api/index.js +12 -0
  54. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static-ngeo/js/{{cookiecutter.package}}module.js +25 -0
  55. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py +39 -0
  56. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/views/__init__.py +0 -0
  57. c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
  58. c2cgeoportal_geoportal/scaffolds/advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile +121 -0
  59. c2cgeoportal_geoportal/scaffolds/create/cookiecutter.json +18 -0
  60. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.dockerignore +14 -0
  61. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.editorconfig +17 -0
  62. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +73 -0
  63. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +50 -0
  64. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +66 -0
  65. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.gitignore +16 -0
  66. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.pre-commit-config.yaml +35 -0
  67. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierignore +1 -0
  68. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierrc.yaml +2 -0
  69. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +75 -0
  70. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +70 -0
  71. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/README.rst +29 -0
  72. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +179 -0
  73. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +22 -0
  74. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
  75. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +2 -0
  76. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +24 -0
  77. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-lib.yaml +513 -0
  78. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +21 -0
  79. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +65 -0
  80. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.yaml +121 -0
  81. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +102 -0
  82. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +69 -0
  83. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/vars.yaml +430 -0
  84. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/locale/en/LC_MESSAGES/{{cookiecutter.package}}_geoportal-client.po +6 -0
  85. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/desktop.css +0 -0
  86. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/iframe_api.css +0 -0
  87. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
  88. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/banner_left.png +0 -0
  89. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/banner_right.png +0 -0
  90. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/blank.png +0 -0
  91. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker-blue.png +0 -0
  92. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker-gold.png +0 -0
  93. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker-green.png +0 -0
  94. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/images/markers/marker.png +0 -0
  95. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/robot.txt.tmpl +3 -0
  96. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/data/Readme.txt +69 -0
  97. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/data/TM_EUROPE_BORDERS-0.3.sql +70 -0
  98. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/demo.map.tmpl +224 -0
  99. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Arial.ttf +0 -0
  100. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Arialbd.ttf +0 -0
  101. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Arialbi.ttf +0 -0
  102. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Ariali.ttf +0 -0
  103. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/NotoSans-Bold.ttf +0 -0
  104. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/NotoSans-BoldItalic.ttf +0 -0
  105. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/NotoSans-Italic.ttf +0 -0
  106. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/NotoSans-Regular.ttf +0 -0
  107. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Verdana.ttf +0 -0
  108. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Verdanab.ttf +0 -0
  109. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Verdanai.ttf +0 -0
  110. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts/Verdanaz.ttf +0 -0
  111. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/fonts.conf +12 -0
  112. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +16 -0
  113. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.map.tmpl +87 -0
  114. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/tinyows.xml.tmpl +36 -0
  115. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Landscape.jrxml +207 -0
  116. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Portrait.jrxml +185 -0
  117. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Landscape.jrxml +200 -0
  118. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Portrait.jrxml +170 -0
  119. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/config.yaml.tmpl +175 -0
  120. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/legend.jrxml +109 -0
  121. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation.properties +4 -0
  122. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation_fr.properties +4 -0
  123. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/logo.png +0 -0
  124. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/north.svg +93 -0
  125. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/results.jrxml +25 -0
  126. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/project.yaml +18 -0
  127. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/pyproject.toml +7 -0
  128. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/qgisserver/pg_service.conf.tmpl +15 -0
  129. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/run_alembic.sh +11 -0
  130. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +126 -0
  131. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +132 -0
  132. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/setup.cfg +7 -0
  133. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +5 -0
  134. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/__init__.py +0 -0
  135. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/test_app.py +78 -0
  136. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tilegeneration/config.yaml.tmpl +195 -0
  137. c2cgeoportal_geoportal/scaffolds/update/cookiecutter.json +18 -0
  138. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/.upgrade.yaml +67 -0
  139. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +304 -0
  140. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
  141. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/.CONST_vars.yaml.swp +0 -0
  142. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_config-schema.yaml +927 -0
  143. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_vars.yaml +1503 -0
  144. c2cgeoportal_geoportal/scripts/__init__.py +64 -0
  145. c2cgeoportal_geoportal/scripts/c2cupgrade.py +879 -0
  146. c2cgeoportal_geoportal/scripts/create_demo_theme.py +83 -0
  147. c2cgeoportal_geoportal/scripts/manage_users.py +140 -0
  148. c2cgeoportal_geoportal/scripts/pcreate.py +296 -0
  149. c2cgeoportal_geoportal/scripts/theme2fts.py +347 -0
  150. c2cgeoportal_geoportal/scripts/urllogin.py +81 -0
  151. c2cgeoportal_geoportal/templates/login.html +90 -0
  152. c2cgeoportal_geoportal/templates/notlogin.html +62 -0
  153. c2cgeoportal_geoportal/templates/testi18n.html +12 -0
  154. c2cgeoportal_geoportal/views/__init__.py +59 -0
  155. c2cgeoportal_geoportal/views/dev.py +57 -0
  156. c2cgeoportal_geoportal/views/dynamic.py +208 -0
  157. c2cgeoportal_geoportal/views/entry.py +174 -0
  158. c2cgeoportal_geoportal/views/fulltextsearch.py +189 -0
  159. c2cgeoportal_geoportal/views/geometry_processing.py +75 -0
  160. c2cgeoportal_geoportal/views/i18n.py +129 -0
  161. c2cgeoportal_geoportal/views/layers.py +713 -0
  162. c2cgeoportal_geoportal/views/login.py +684 -0
  163. c2cgeoportal_geoportal/views/mapserverproxy.py +234 -0
  164. c2cgeoportal_geoportal/views/memory.py +90 -0
  165. c2cgeoportal_geoportal/views/ogcproxy.py +120 -0
  166. c2cgeoportal_geoportal/views/pdfreport.py +245 -0
  167. c2cgeoportal_geoportal/views/printproxy.py +143 -0
  168. c2cgeoportal_geoportal/views/profile.py +192 -0
  169. c2cgeoportal_geoportal/views/proxy.py +261 -0
  170. c2cgeoportal_geoportal/views/raster.py +233 -0
  171. c2cgeoportal_geoportal/views/resourceproxy.py +73 -0
  172. c2cgeoportal_geoportal/views/shortener.py +152 -0
  173. c2cgeoportal_geoportal/views/theme.py +1322 -0
  174. c2cgeoportal_geoportal/views/tinyowsproxy.py +189 -0
  175. c2cgeoportal_geoportal/views/vector_tiles.py +83 -0
  176. {c2cgeoportal_geoportal-2.3.5.79.dist-info → c2cgeoportal_geoportal-2.9rc44.dist-info}/METADATA +21 -24
  177. c2cgeoportal_geoportal-2.9rc44.dist-info/RECORD +193 -0
  178. {c2cgeoportal_geoportal-2.3.5.79.dist-info → c2cgeoportal_geoportal-2.9rc44.dist-info}/WHEEL +1 -1
  179. c2cgeoportal_geoportal-2.9rc44.dist-info/entry_points.txt +28 -0
  180. c2cgeoportal_geoportal-2.9rc44.dist-info/top_level.txt +2 -0
  181. tests/__init__.py +100 -0
  182. tests/test_cachebuster.py +71 -0
  183. tests/test_caching.py +275 -0
  184. tests/test_checker.py +85 -0
  185. tests/test_decimaljson.py +47 -0
  186. tests/test_headerstween.py +64 -0
  187. tests/test_i18n.py +31 -0
  188. tests/test_init.py +193 -0
  189. tests/test_locale_negociator.py +69 -0
  190. tests/test_mapserverproxy_route_predicate.py +64 -0
  191. tests/test_raster.py +267 -0
  192. tests/test_wmstparsing.py +238 -0
  193. tests/xmlstr.py +103 -0
  194. c2cgeoportal_geoportal-2.3.5.79.dist-info/DESCRIPTION.rst +0 -8
  195. c2cgeoportal_geoportal-2.3.5.79.dist-info/RECORD +0 -7
  196. c2cgeoportal_geoportal-2.3.5.79.dist-info/entry_points.txt +0 -22
  197. c2cgeoportal_geoportal-2.3.5.79.dist-info/metadata.json +0 -1
  198. c2cgeoportal_geoportal-2.3.5.79.dist-info/top_level.txt +0 -1
@@ -0,0 +1,176 @@
1
+ # Copyright (c) 2012-2024, Camptocamp SA
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ # The views and conclusions contained in the software and documentation are those
25
+ # of the authors and should not be interpreted as representing official policies,
26
+ # either expressed or implied, of the FreeBSD Project.
27
+
28
+
29
+ import inspect
30
+ import logging
31
+ from collections.abc import Callable, Mapping, Sequence
32
+ from typing import TYPE_CHECKING, Any
33
+
34
+ import pyramid.interfaces
35
+ import zope.interface
36
+ from dogpile.cache.api import NO_VALUE, CacheBackend, CachedValue, NoValue
37
+ from dogpile.cache.backends.memory import MemoryBackend
38
+ from dogpile.cache.backends.redis import RedisBackend, RedisSentinelBackend
39
+ from dogpile.cache.region import CacheRegion, make_region
40
+ from dogpile.cache.util import sha1_mangle_key
41
+ from sqlalchemy.orm.util import identity_key
42
+
43
+ from c2cgeoportal_commons.models import Base
44
+
45
+ if TYPE_CHECKING:
46
+ from dogpile.cache.api import SerializedReturnType
47
+ else:
48
+ SerializedReturnType = Any
49
+
50
+ _LOG = logging.getLogger(__name__)
51
+ _REGION: dict[str, CacheRegion] = {}
52
+ MEMORY_CACHE_DICT: dict[str, Any] = {}
53
+
54
+
55
+ def map_dbobject(item: type[Any]) -> Any:
56
+ """Get an cache identity key for the cache."""
57
+ return identity_key(item) if isinstance(item, Base) else item
58
+
59
+
60
+ def keygen_function(namespace: Any, function: Callable[..., Any]) -> Callable[..., str]:
61
+ """
62
+ Return a function that generates a string key.
63
+
64
+ Based on a given function as well as arguments to the returned function itself.
65
+
66
+ This is used by :meth:`.CacheRegion.cache_on_arguments` to generate a cache key from a decorated function.
67
+ """
68
+
69
+ if namespace is None:
70
+ namespace = (function.__module__, function.__name__)
71
+ else:
72
+ namespace = (function.__module__, function.__name__, namespace)
73
+
74
+ args = inspect.getfullargspec(function)
75
+ ignore_first_argument = args[0] and args[0][0] in ("self", "cls")
76
+
77
+ def generate_key(*args: Any, **kw: Any) -> str:
78
+ if kw:
79
+ raise ValueError("key creation function does not accept keyword arguments.")
80
+ parts: list[str] = []
81
+ parts.extend(namespace)
82
+ if ignore_first_argument:
83
+ args = args[1:]
84
+ new_args = [
85
+ arg for arg in args if pyramid.interfaces.IRequest not in zope.interface.implementedBy(type(arg))
86
+ ]
87
+ parts.extend(map(str, map(map_dbobject, new_args)))
88
+ return "|".join(parts)
89
+
90
+ return generate_key
91
+
92
+
93
+ def init_region(conf: dict[str, Any], region: str) -> CacheRegion:
94
+ """Initialize the caching module."""
95
+ cache_region = get_region(region)
96
+ _configure_region(conf, cache_region)
97
+ return cache_region
98
+
99
+
100
+ def _configure_region(conf: dict[str, Any], cache_region: CacheRegion) -> None:
101
+ kwargs: dict[str, Any] = {"replace_existing_backend": True}
102
+ backend = conf["backend"]
103
+ kwargs.update({k: conf[k] for k in conf if k != "backend"})
104
+ kwargs.setdefault("arguments", {}).setdefault("cache_dict", MEMORY_CACHE_DICT)
105
+ cache_region.configure(backend, **kwargs)
106
+
107
+
108
+ def get_region(region: str) -> CacheRegion:
109
+ """Return a cache region."""
110
+ if region not in _REGION:
111
+ _REGION[region] = make_region(function_key_generator=keygen_function)
112
+ return _REGION[region]
113
+
114
+
115
+ def invalidate_region(region: str | None = None) -> None:
116
+ """Invalidate a cache region."""
117
+ if region is None:
118
+ for cache_region in _REGION.values():
119
+ cache_region.invalidate() # type: ignore[no-untyped-call]
120
+ else:
121
+ get_region(region).invalidate() # type: ignore[no-untyped-call]
122
+
123
+
124
+ class HybridRedisBackend(CacheBackend):
125
+ """A Dogpile cache backend with a memory cache backend in front of a Redis backend for performance."""
126
+
127
+ def __init__(self, arguments: dict[str, Any]):
128
+ self._use_memory_cache = not arguments.pop("disable_memory_cache", False)
129
+ self._memory: CacheBackend = MemoryBackend( # type: ignore[no-untyped-call]
130
+ {"cache_dict": arguments.pop("cache_dict", {})},
131
+ )
132
+ self._redis: CacheBackend = RedisBackend(arguments) # type: ignore[no-untyped-call]
133
+
134
+ def get(self, key: str) -> CachedValue | bytes | NoValue:
135
+ value = self._memory.get(key)
136
+ if value == NO_VALUE:
137
+ val = self._redis.get_serialized(sha1_mangle_key(key.encode())) # type: ignore[no-untyped-call]
138
+ if val in (None, NO_VALUE):
139
+ return NO_VALUE
140
+ assert isinstance(val, bytes)
141
+ value = self._redis.deserializer(val) # type: ignore[misc]
142
+ if value != NO_VALUE and self._use_memory_cache:
143
+ assert isinstance(value, (CachedValue, bytes))
144
+ self._memory.set(key, value)
145
+ return value
146
+
147
+ def get_multi(self, keys: Sequence[str]) -> list[CachedValue | bytes | NoValue]:
148
+ return [self.get(key) for key in keys]
149
+
150
+ def set(self, key: str, value: CachedValue | bytes) -> None:
151
+ if self._use_memory_cache:
152
+ self._memory.set(key, value)
153
+ self._redis.set_serialized(
154
+ sha1_mangle_key(key.encode()), # type: ignore[no-untyped-call]
155
+ self._redis.serializer(value), # type: ignore[misc]
156
+ )
157
+
158
+ def set_multi(self, mapping: Mapping[str, CachedValue | bytes]) -> None:
159
+ for key, value in mapping.items():
160
+ self.set(key, value)
161
+
162
+ def delete(self, key: str) -> None:
163
+ self._memory.delete(key)
164
+ self._redis.delete(key)
165
+
166
+ def delete_multi(self, keys: Sequence[str]) -> None:
167
+ self._memory.delete_multi(keys)
168
+ self._redis.delete_multi(keys)
169
+
170
+
171
+ class HybridRedisSentinelBackend(HybridRedisBackend):
172
+ """Same as HybridRedisBackend but using the Redis Sentinel."""
173
+
174
+ def __init__(self, arguments: dict[str, Any]):
175
+ super().__init__(arguments)
176
+ self._redis = RedisSentinelBackend(arguments) # type: ignore[no-untyped-call]
@@ -0,0 +1,80 @@
1
+ # Copyright (c) 2011-2024, Camptocamp SA
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ # The views and conclusions contained in the software and documentation are those
25
+ # of the authors and should not be interpreted as representing official policies,
26
+ # either expressed or implied, of the FreeBSD Project.
27
+ import logging
28
+ from typing import Any, cast
29
+
30
+ import c2cwsgiutils.health_check
31
+ import pyramid.config
32
+ import pyramid.request
33
+ import requests
34
+
35
+ from c2cgeoportal_geoportal.lib.checker import build_url
36
+
37
+ _LOG = logging.getLogger(__name__)
38
+
39
+
40
+ def init(config: pyramid.config.Configurator, health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
41
+ """
42
+ Initialize the check collector.
43
+
44
+ Add him in the c2cwsgichecks.
45
+ """
46
+ global_settings = config.get_settings()
47
+ if "check_collector" not in global_settings:
48
+ return
49
+ settings = global_settings["check_collector"]
50
+ c2c_base = global_settings.get("c2c.base_path", "")
51
+
52
+ max_level = settings["max_level"]
53
+
54
+ for host in settings["hosts"]:
55
+
56
+ class Check:
57
+ def __init__(self, host: dict[str, Any]):
58
+ self.host = host
59
+
60
+ def __call__(self, request: pyramid.request.Request) -> dict[str, Any] | None:
61
+ params = request.params
62
+ display = self.host["display"]
63
+ if "host" not in params or display == params["host"]:
64
+ url_headers = build_url(
65
+ "check_collector",
66
+ f"{self.host['url'].rstrip('/')}/{c2c_base.strip('/')}/health_check",
67
+ request,
68
+ )
69
+ r = requests.get(
70
+ params={"max_level": str(self.host.get("max_level", max_level))},
71
+ timeout=120,
72
+ **url_headers, # type: ignore
73
+ )
74
+ r.raise_for_status()
75
+ return cast(dict[str, Any], r.json())
76
+ return None
77
+
78
+ health_check.add_custom_check(
79
+ name="check_collector_" + host["display"], check_cb=Check(host), level=settings["level"]
80
+ )
@@ -0,0 +1,295 @@
1
+ # Copyright (c) 2011-2024, Camptocamp SA
2
+ # All rights reserved.
3
+
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+
7
+ # 1. Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
10
+ # this list of conditions and the following disclaimer in the documentation
11
+ # and/or other materials provided with the distribution.
12
+
13
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ # The views and conclusions contained in the software and documentation are those
25
+ # of the authors and should not be interpreted as representing official policies,
26
+ # either expressed or implied, of the FreeBSD Project.
27
+
28
+ import json
29
+ import logging
30
+ import os
31
+ import subprocess
32
+ from collections.abc import Mapping
33
+ from time import sleep
34
+ from typing import Any, cast
35
+ from urllib.parse import urljoin
36
+
37
+ import c2cwsgiutils.health_check
38
+ import pyramid.config
39
+ import pyramid.request
40
+ import requests
41
+
42
+ _LOG = logging.getLogger(__name__)
43
+
44
+
45
+ def build_url(
46
+ name: str, path: str, request: pyramid.request.Request, headers: dict[str, str] | None = None
47
+ ) -> dict[str, str | dict[str, str]]:
48
+ """Build an URL and headers for the checkers."""
49
+ base_internal_url = request.registry.settings["checker"]["base_internal_url"]
50
+ url = urljoin(base_internal_url, path)
51
+
52
+ forward_host = request.registry.settings["checker"].get("forward_host", False)
53
+ headers = _build_headers(request, headers)
54
+ if forward_host:
55
+ headers["Host"] = request.host
56
+
57
+ _LOG.debug("%s, URL: %s", name, url)
58
+ return {"url": url, "headers": headers}
59
+
60
+
61
+ def _build_headers(request: pyramid.request.Request, headers: dict[str, str] | None = None) -> dict[str, str]:
62
+ if headers is None:
63
+ headers = {}
64
+ headers["Cache-Control"] = "no-cache"
65
+ settings = request.registry.settings.get("checker", {})
66
+ for header in settings.get("forward_headers", []):
67
+ value = request.headers.get(header)
68
+ if value is not None:
69
+ headers[header] = value
70
+ return headers
71
+
72
+
73
+ def _routes(settings: dict[str, Any], health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
74
+ routes_settings = settings["routes"]
75
+ for route in routes_settings["routes"]:
76
+ if route.get("checker_name", route["name"]) not in routes_settings["disable"]:
77
+ name = "checker_routes_" + route.get("checker_name", route["name"])
78
+
79
+ class GetRequest:
80
+ """Get the request information about the current route name."""
81
+
82
+ def __init__(self, route_name: str, type_: str) -> None:
83
+ self.route_name = route_name
84
+ self.type = type_
85
+
86
+ def __call__(self, request: pyramid.request.Request) -> str | dict[str, str]:
87
+ return build_url("route", request.route_path(self.route_name), request)[self.type]
88
+
89
+ health_check.add_url_check(
90
+ url=GetRequest(route["name"], "url"), # type: ignore
91
+ name=name,
92
+ params=route.get("params", None),
93
+ headers=GetRequest(route["name"], "headers"), # type: ignore
94
+ level=route["level"],
95
+ timeout=30,
96
+ )
97
+
98
+
99
+ def _pdf3(settings: dict[str, Any], health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
100
+ print_settings = settings["print"]
101
+ if "spec" not in print_settings:
102
+ return
103
+
104
+ def check(request: pyramid.request.Request) -> None:
105
+ path = request.route_path("printproxy_report_create", format="pdf")
106
+ url_headers = build_url("Check the printproxy request (create)", path, request)
107
+
108
+ session = requests.session()
109
+ resp = session.post(json=print_settings["spec"], timeout=30, **url_headers) # type: ignore
110
+ resp.raise_for_status()
111
+
112
+ job = resp.json()
113
+
114
+ path = request.route_path("printproxy_status", ref=job["ref"])
115
+ url_headers = build_url("Check the printproxy pdf status", path, request)
116
+ done = False
117
+ while not done:
118
+ sleep(1)
119
+ resp = session.get(timeout=30, **url_headers) # type: ignore
120
+ resp.raise_for_status()
121
+
122
+ status = resp.json()
123
+ if "error" in status:
124
+ raise Exception( # pylint: disable=broad-exception-raised
125
+ f"Failed to do the printing: {status['error']}",
126
+ )
127
+ done = status["done"]
128
+
129
+ path = request.route_path("printproxy_report_get", ref=job["ref"])
130
+ url_headers = build_url("Check the printproxy pdf retrieve", path, request)
131
+ resp = session.get(timeout=30, **url_headers) # type: ignore
132
+ resp.raise_for_status()
133
+
134
+ health_check.add_custom_check(name="checker_print", check_cb=check, level=print_settings["level"])
135
+
136
+
137
+ def _fts(settings: dict[str, Any], health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
138
+ fts_settings = settings["fulltextsearch"]
139
+ if fts_settings.get("disable", False):
140
+ return
141
+
142
+ def get_both(request: pyramid.request.Request) -> dict[str, str | dict[str, str]]:
143
+ return build_url("Check the fulltextsearch", request.route_path("fulltextsearch"), request)
144
+
145
+ def check(_request: pyramid.request.Request, response: pyramid.response.Response) -> None:
146
+ assert response.json()["features"], "No result"
147
+
148
+ health_check.add_url_check(
149
+ name="checker_fulltextsearch",
150
+ url=lambda r: get_both(r)["url"], # type: ignore
151
+ headers=lambda r: get_both(r)["headers"], # type: ignore
152
+ params={"query": fts_settings["search"], "limit": "1"},
153
+ check_cb=check,
154
+ level=fts_settings["level"],
155
+ )
156
+
157
+
158
+ def _themes_errors(settings: dict[str, Any], health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
159
+ from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel
160
+ from c2cgeoportal_commons.models.main import Interface # pylint: disable=import-outside-toplevel
161
+
162
+ assert DBSession is not None
163
+
164
+ themes_settings = settings["themes"]
165
+ default_params = themes_settings.get("params", {})
166
+ interfaces_settings = themes_settings["interfaces"]
167
+
168
+ def check(request: pyramid.request.Request) -> None:
169
+ path = request.route_path("themes")
170
+ session = requests.session()
171
+ for (interface,) in DBSession.query(Interface.name).all():
172
+ params: dict[str, str] = {}
173
+ params.update(default_params)
174
+ params.update(interfaces_settings.get(interface, {}).get("params", {}))
175
+ params["interface"] = interface
176
+
177
+ interface_url_headers = build_url("checker_themes " + interface, path, request)
178
+
179
+ response = session.get(params=params, timeout=120, **interface_url_headers) # type: ignore
180
+ response.raise_for_status()
181
+
182
+ result = response.json()
183
+ if result["errors"]:
184
+ raise c2cwsgiutils.health_check.JsonCheckException(
185
+ f"Interface '{interface}' has error in Theme.", result["errors"]
186
+ )
187
+
188
+ health_check.add_custom_check(name="checker_themes", check_cb=check, level=themes_settings["level"])
189
+
190
+
191
+ def _lang_files(
192
+ global_settings: dict[str, Any],
193
+ settings: dict[str, Any],
194
+ health_check: c2cwsgiutils.health_check.HealthCheck,
195
+ ) -> None:
196
+ lang_settings = settings["lang"]
197
+ available_locale_names = global_settings["available_locale_names"]
198
+
199
+ default_name = global_settings["default_locale_name"]
200
+ assert default_name in available_locale_names, (
201
+ f"default_locale_name '{default_name}' not in available_locale_names: "
202
+ f"{', '.join(available_locale_names)}"
203
+ )
204
+
205
+ for type_ in lang_settings.get("files", []):
206
+ for lang in available_locale_names:
207
+ if type_ == "ngeo":
208
+ url = f"/etc/geomapfish/static/{lang}.json"
209
+ else:
210
+ raise Exception( # pylint: disable=broad-exception-raised
211
+ f"Your language type value '{type_}' is not valid, available values [ngeo]",
212
+ )
213
+
214
+ name = f"checker_lang_{type_}_{lang}"
215
+
216
+ class GetRequest:
217
+ """Get the request information about the current route name."""
218
+
219
+ def __init__(self, name: str, url: str, lang: str, type_: str) -> None:
220
+ self.name = name
221
+ self.url = url
222
+ self.lang = lang
223
+ self.type = type_
224
+
225
+ def __call__(self, request: pyramid.request.Request) -> str | Mapping[str, str]:
226
+ return build_url(
227
+ self.name,
228
+ request.static_path(
229
+ self.url.format(package=global_settings["package"], lang=self.lang)
230
+ ),
231
+ request,
232
+ )[self.type]
233
+
234
+ health_check.add_url_check(
235
+ name=name,
236
+ url=GetRequest(name, url, lang, "url"), # type: ignore
237
+ headers=GetRequest(name, url, lang, "headers"), # type: ignore
238
+ level=lang_settings["level"],
239
+ )
240
+
241
+
242
+ def _phantomjs(settings: dict[str, Any], health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
243
+ phantomjs_settings = settings["phantomjs"]
244
+ for route in phantomjs_settings["routes"]:
245
+ if route.get("checker_name", route["name"]) in phantomjs_settings["disable"]:
246
+ continue
247
+
248
+ class _Check:
249
+ def __init__(self, route: dict[str, Any]) -> None:
250
+ self.route = route
251
+
252
+ def __call__(self, request: pyramid.request.Request) -> None:
253
+ path = request.route_path(self.route["name"], _query=self.route.get("params", {}))
254
+ url: str = cast(str, build_url("Check", path, request)["url"])
255
+
256
+ cmd: list[str] = ["check-example", url]
257
+ env = dict(os.environ)
258
+ for name, value in self.route.get("environment", {}).items():
259
+ if isinstance(value, (list, dict)):
260
+ value = json.dumps(value)
261
+ elif not isinstance(value, str):
262
+ value = str(value)
263
+ env[name] = value
264
+
265
+ try:
266
+ subprocess.check_output(cmd, env=env, timeout=70)
267
+ except subprocess.CalledProcessError as exception:
268
+ raise Exception( # pylint: disable=broad-exception-raised
269
+ f"{' '.join(exception.cmd)} exit with code: {exception.returncode}\n"
270
+ f"{exception.output.decode('utf-8')[:10000]}"
271
+ ) from exception
272
+ except subprocess.TimeoutExpired as exception:
273
+ raise Exception( # pylint: disable=broad-exception-raised
274
+ f"""Timeout:
275
+ command: {' '.join(exception.cmd)}
276
+ output:
277
+ {exception.output.decode('utf-8')}"""
278
+ ) from exception
279
+
280
+ name = "checker_phantomjs_" + route.get("checker_name", route["name"])
281
+ health_check.add_custom_check(name=name, check_cb=_Check(route), level=route["level"])
282
+
283
+
284
+ def init(config: pyramid.config.Configurator, health_check: c2cwsgiutils.health_check.HealthCheck) -> None:
285
+ """Initialize the checkers."""
286
+ global_settings = config.get_settings()
287
+ if "checker" not in global_settings:
288
+ return
289
+ settings = global_settings["checker"]
290
+ _routes(settings, health_check)
291
+ _pdf3(settings, health_check)
292
+ _fts(settings, health_check)
293
+ _themes_errors(settings, health_check)
294
+ _lang_files(global_settings, settings, health_check)
295
+ _phantomjs(settings, health_check)