c2cgeoportal-geoportal 2.6.0__py2.py3-none-any.whl → 2.8.1.180__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- c2cgeoportal_geoportal/__init__.py +245 -95
- c2cgeoportal_geoportal/lib/__init__.py +67 -43
- c2cgeoportal_geoportal/lib/authentication.py +50 -26
- c2cgeoportal_geoportal/lib/bashcolor.py +17 -13
- c2cgeoportal_geoportal/lib/cacheversion.py +16 -8
- c2cgeoportal_geoportal/lib/caching.py +65 -193
- c2cgeoportal_geoportal/lib/check_collector.py +17 -10
- c2cgeoportal_geoportal/lib/checker.py +67 -65
- c2cgeoportal_geoportal/lib/common_headers.py +167 -0
- c2cgeoportal_geoportal/lib/dbreflection.py +61 -46
- c2cgeoportal_geoportal/lib/filter_capabilities.py +126 -88
- c2cgeoportal_geoportal/lib/fulltextsearch.py +6 -5
- c2cgeoportal_geoportal/lib/functionality.py +20 -17
- c2cgeoportal_geoportal/lib/headers.py +14 -5
- c2cgeoportal_geoportal/lib/i18n.py +4 -4
- c2cgeoportal_geoportal/lib/layers.py +30 -11
- c2cgeoportal_geoportal/lib/lingua_extractor.py +363 -240
- c2cgeoportal_geoportal/lib/loader.py +11 -16
- c2cgeoportal_geoportal/lib/metrics.py +28 -17
- c2cgeoportal_geoportal/lib/oauth2.py +392 -206
- c2cgeoportal_geoportal/lib/wmstparsing.py +105 -84
- c2cgeoportal_geoportal/lib/xsd.py +26 -16
- c2cgeoportal_geoportal/resources.py +15 -9
- c2cgeoportal_geoportal/scaffolds/advance_create/ci/config.yaml +26 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.dockerignore +6 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/.eslintrc.yaml +19 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+dot+prospector.yaml → advance_create/{{cookiecutter.project}}/geoportal/.prospector.yaml} +8 -2
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/Dockerfile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Dockerfile} +22 -15
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/alembic.yaml_tmpl → advance_create/{{cookiecutter.project}}/geoportal/alembic.yaml} +1 -1
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/development.ini_tmpl → advance_create/{{cookiecutter.project}}/geoportal/development.ini} +34 -15
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +100 -0
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-client.cfg +1 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/production.ini +38 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/setup.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/setup.py} +6 -7
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tsconfig.json +8 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +77 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/webpack.apps.js_tmpl → advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js} +29 -28
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.commons.js +4 -7
- c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/webpack.config.js +1 -1
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +42 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/authentication.py +10 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/dev.py +14 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/models.py +8 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/multi_organization.py +7 -0
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/resources.py +4 -3
- 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
- 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
- c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal/subscribers.py_tmpl → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/subscribers.py} +1 -3
- c2cgeoportal_geoportal/scaffolds/advance_update/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/{update/geoportal/CONST_Makefile_tmpl → advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile} +3 -27
- c2cgeoportal_geoportal/scaffolds/create/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.dockerignore +14 -0
- c2cgeoportal_geoportal/scaffolds/create/{+dot+editorconfig → {{cookiecutter.project}}/.editorconfig} +2 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +57 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +46 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +66 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.gitignore +16 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierignore +1 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.prettierrc.yaml +2 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +76 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +70 -0
- c2cgeoportal_geoportal/scaffolds/create/{README.rst_tmpl → {{cookiecutter.project}}/README.rst} +4 -4
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +186 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +22 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +26 -0
- c2cgeoportal_geoportal/scaffolds/create/{docker-compose-lib.yaml → {{cookiecutter.project}}/docker-compose-lib.yaml} +165 -22
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +23 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +66 -0
- c2cgeoportal_geoportal/scaffolds/create/{docker-compose.yaml → {{cookiecutter.project}}/docker-compose.yaml} +20 -15
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +101 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +69 -0
- c2cgeoportal_geoportal/scaffolds/create/{geoportal/vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/vars.yaml} +126 -36
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/mobile.css +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/Readme.txt +3 -3
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/demo.map.tmpl +224 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +15 -0
- c2cgeoportal_geoportal/scaffolds/create/{mapserver/mapserver.map.tmpl_tmpl → {{cookiecutter.project}}/mapserver/mapserver.map.tmpl} +9 -18
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Landscape.jrxml +13 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A3_Portrait.jrxml +13 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Landscape.jrxml +13 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/A4_Portrait.jrxml +13 -8
- c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/config.yaml.tmpl +11 -4
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation.properties +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/localisation_fr.properties +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{project.yaml_tmpl → {{cookiecutter.project}}/project.yaml} +6 -6
- c2cgeoportal_geoportal/scaffolds/create/{pyproject.toml → {{cookiecutter.project}}/pyproject.toml} +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{qgisserver/pg_service.conf.tmpl_tmpl → {{cookiecutter.project}}/qgisserver/pg_service.conf.tmpl} +2 -2
- c2cgeoportal_geoportal/scaffolds/create/{run_alembic.sh → {{cookiecutter.project}}/run_alembic.sh} +3 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +110 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +114 -0
- c2cgeoportal_geoportal/scaffolds/create/{setup.cfg_tmpl → {{cookiecutter.project}}/setup.cfg} +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/__init__.py +0 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/test_app.py +38 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tilegeneration/config.yaml.tmpl +195 -0
- c2cgeoportal_geoportal/scaffolds/update/cookiecutter.json +18 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/.upgrade.yaml +61 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +273 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
- c2cgeoportal_geoportal/scaffolds/update/{geoportal → {{cookiecutter.project}}/geoportal}/CONST_config-schema.yaml +64 -17
- c2cgeoportal_geoportal/scaffolds/update/{geoportal/CONST_vars.yaml_tmpl → {{cookiecutter.project}}/geoportal/CONST_vars.yaml} +396 -19
- c2cgeoportal_geoportal/scripts/__init__.py +16 -30
- c2cgeoportal_geoportal/scripts/c2cupgrade.py +272 -234
- c2cgeoportal_geoportal/scripts/create_demo_theme.py +3 -6
- c2cgeoportal_geoportal/scripts/manage_users.py +34 -39
- c2cgeoportal_geoportal/scripts/pcreate.py +310 -0
- c2cgeoportal_geoportal/scripts/theme2fts.py +128 -24
- c2cgeoportal_geoportal/scripts/urllogin.py +19 -11
- c2cgeoportal_geoportal/templates/login.html +88 -84
- c2cgeoportal_geoportal/templates/notlogin.html +59 -59
- c2cgeoportal_geoportal/templates/testi18n.html +6 -8
- c2cgeoportal_geoportal/views/__init__.py +23 -6
- c2cgeoportal_geoportal/views/dev.py +9 -7
- c2cgeoportal_geoportal/views/dynamic.py +56 -19
- c2cgeoportal_geoportal/views/entry.py +85 -24
- c2cgeoportal_geoportal/views/fulltextsearch.py +29 -23
- c2cgeoportal_geoportal/views/geometry_processing.py +17 -9
- c2cgeoportal_geoportal/views/i18n.py +91 -9
- c2cgeoportal_geoportal/views/layers.py +166 -133
- c2cgeoportal_geoportal/views/login.py +161 -93
- c2cgeoportal_geoportal/views/mapserverproxy.py +47 -31
- c2cgeoportal_geoportal/views/memory.py +12 -12
- c2cgeoportal_geoportal/views/ogcproxy.py +52 -30
- c2cgeoportal_geoportal/views/pdfreport.py +30 -26
- c2cgeoportal_geoportal/views/printproxy.py +60 -52
- c2cgeoportal_geoportal/views/profile.py +24 -23
- c2cgeoportal_geoportal/views/proxy.py +88 -72
- c2cgeoportal_geoportal/views/raster.py +37 -26
- c2cgeoportal_geoportal/views/resourceproxy.py +13 -11
- c2cgeoportal_geoportal/views/shortener.py +27 -25
- c2cgeoportal_geoportal/views/theme.py +472 -332
- c2cgeoportal_geoportal/views/tinyowsproxy.py +42 -44
- c2cgeoportal_geoportal/views/vector_tiles.py +80 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/METADATA +19 -8
- c2cgeoportal_geoportal-2.8.1.180.dist-info/RECORD +191 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/WHEEL +1 -1
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/entry_points.txt +3 -0
- tests/__init__.py +10 -5
- tests/test_cachebuster.py +3 -5
- tests/test_caching.py +18 -26
- tests/test_checker.py +1 -3
- tests/test_decimaljson.py +5 -5
- tests/test_headerstween.py +1 -3
- tests/test_i18n.py +2 -2
- tests/test_init.py +16 -20
- tests/test_locale_negociator.py +4 -6
- tests/test_mapserverproxy_route_predicate.py +1 -4
- tests/test_raster.py +15 -17
- tests/test_wmstparsing.py +10 -12
- tests/xmlstr.py +1 -3
- c2cgeoportal_geoportal/scaffolds/__init__.py +0 -227
- c2cgeoportal_geoportal/scaffolds/create/+dot+dockerignore_tmpl +0 -12
- c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/main.yaml_tmpl +0 -89
- c2cgeoportal_geoportal/scaffolds/create/+dot+github/workflows/rebuild.yaml_tmpl +0 -78
- c2cgeoportal_geoportal/scaffolds/create/+dot+gitignore_tmpl +0 -16
- c2cgeoportal_geoportal/scaffolds/create/Dockerfile_tmpl +0 -67
- c2cgeoportal_geoportal/scaffolds/create/Makefile +0 -3
- c2cgeoportal_geoportal/scaffolds/create/build_tmpl +0 -167
- c2cgeoportal_geoportal/scaffolds/create/ci/config.yaml_tmpl +0 -23
- c2cgeoportal_geoportal/scaffolds/create/ci/requirements.txt +0 -1
- c2cgeoportal_geoportal/scaffolds/create/ci/trigger +0 -68
- c2cgeoportal_geoportal/scaffolds/create/docker-compose.override.sample.yaml +0 -54
- c2cgeoportal_geoportal/scaffolds/create/env.default_tmpl +0 -67
- c2cgeoportal_geoportal/scaffolds/create/env.project_tmpl +0 -48
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+dockerignore_tmpl +0 -6
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+dot+eslintrc_tmpl +0 -15
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/__init__.py_tmpl +0 -58
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/models.py_tmpl +0 -10
- c2cgeoportal_geoportal/scaffolds/create/geoportal/+package+_geoportal/static/robot.txt +0 -3
- c2cgeoportal_geoportal/scaffolds/create/geoportal/production.ini_tmpl +0 -106
- c2cgeoportal_geoportal/scaffolds/create/geoportal/tools/extract-messages.js +0 -39
- c2cgeoportal_geoportal/scaffolds/create/geoportal/tsconfig.json_tmpl +0 -9
- c2cgeoportal_geoportal/scaffolds/create/geoportal/webpack.api.js_tmpl +0 -72
- c2cgeoportal_geoportal/scaffolds/create/mapserver/demo.map.tmpl_tmpl +0 -262
- c2cgeoportal_geoportal/scaffolds/create/mapserver/tinyows.xml +0 -36
- c2cgeoportal_geoportal/scaffolds/create/print/print-apps/+package+/config.yaml +0 -168
- c2cgeoportal_geoportal/scaffolds/create/qgisserver/geomapfish.yaml.tmpl_tmpl +0 -16
- c2cgeoportal_geoportal/scaffolds/create/spell-ignore-words.txt +0 -1
- c2cgeoportal_geoportal/scaffolds/create/tilegeneration/config.yaml.tmpl_tmpl +0 -185
- c2cgeoportal_geoportal/scaffolds/create/yamllint.yaml +0 -11
- c2cgeoportal_geoportal/scaffolds/update/+dot+upgrade.yaml_tmpl +0 -181
- c2cgeoportal_geoportal/scaffolds/update/CONST_CHANGELOG.txt_tmpl +0 -454
- c2cgeoportal_geoportal/templates/dynamic.js +0 -21
- c2cgeoportal_geoportal-2.6.0.dist-info/RECORD +0 -173
- /c2cgeoportal_geoportal/{scaffolds/create/geoportal/+package+_geoportal/static/css/desktop.css → py.typed} +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create/geoportal/Makefile_tmpl → advance_create/{{cookiecutter.project}}/geoportal/Makefile} +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/alembic.ini +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/language_mapping +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/lingua-server.cfg +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create → advance_create/{{cookiecutter.project}}}/geoportal/requirements.txt +0 -0
- /c2cgeoportal_geoportal/scaffolds/{create/geoportal/+package+_geoportal → advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/views/__init__.py +0 -0
- /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
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/iframe_api.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/desktop.css} +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal/static/css/mobile.css → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/static/css/iframe_api.css} +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_left.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/banner_right.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/blank.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-blue.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-gold.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker-green.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/images/markers/marker.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{geoportal/+package+_geoportal → {{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal}/static/robot.txt.tmpl +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/data/TM_EUROPE_BORDERS-0.3.sql +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arial.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbd.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Arialbi.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Ariali.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Bold.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-BoldItalic.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Italic.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/NotoSans-Regular.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdana.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanab.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanai.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts/Verdanaz.ttf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/fonts.conf +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{mapserver → {{cookiecutter.project}}/mapserver}/tinyows.xml.tmpl +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/legend.jrxml +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/logo.png +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/north.svg +0 -0
- /c2cgeoportal_geoportal/scaffolds/create/{print/print-apps/+package+ → {{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}}/results.jrxml +0 -0
- {c2cgeoportal_geoportal-2.6.0.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -27,17 +25,36 @@
|
|
27
25
|
# of the authors and should not be interpreted as representing official policies,
|
28
26
|
# either expressed or implied, of the FreeBSD Project.
|
29
27
|
|
28
|
+
from typing import Dict, List
|
30
29
|
|
30
|
+
import pyramid.config
|
31
|
+
import pyramid.request
|
31
32
|
from pyramid.httpexceptions import HTTPFound
|
32
33
|
|
33
34
|
|
34
|
-
def add_ending_slash(request):
|
35
|
+
def add_ending_slash(request: pyramid.request.Request) -> HTTPFound:
|
36
|
+
"""Add an ending slash view."""
|
35
37
|
return HTTPFound(location=request.path + "/")
|
36
38
|
|
37
39
|
|
38
|
-
def add_redirect(config, name, from_, to):
|
39
|
-
|
40
|
+
def add_redirect(config: pyramid.config.Configurator, name: str, from_: str, to: str) -> None:
|
41
|
+
"""Add a redirect view."""
|
42
|
+
|
43
|
+
def redirect_view(request: pyramid.request.Request) -> HTTPFound:
|
40
44
|
return HTTPFound(location=request.route_url(to))
|
41
45
|
|
42
46
|
config.add_route(name, from_, request_method="GET")
|
43
47
|
config.add_view(redirect_view, route_name=name)
|
48
|
+
|
49
|
+
|
50
|
+
def restrict_headers(headers: Dict[str, str], whitelist: List[str], blacklist: List[str]) -> Dict[str, str]:
|
51
|
+
"""
|
52
|
+
Filter headers with a whitelist then a blacklist.
|
53
|
+
|
54
|
+
Some default pyramid headers will be added back by pyramid.
|
55
|
+
"""
|
56
|
+
if len(whitelist) > 0:
|
57
|
+
headers = {key: value for key, value in headers.items() if key in whitelist}
|
58
|
+
|
59
|
+
headers = {key: value for key, value in headers.items() if key not in blacklist}
|
60
|
+
return headers
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2021, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -31,25 +29,29 @@
|
|
31
29
|
import logging
|
32
30
|
import re
|
33
31
|
|
32
|
+
import pyramid.request
|
33
|
+
import pyramid.response
|
34
34
|
from pyramid.httpexceptions import HTTPFound
|
35
35
|
from pyramid.view import view_config
|
36
36
|
|
37
|
+
from c2cgeoportal_commons.lib.url import Url
|
37
38
|
from c2cgeoportal_geoportal.views.proxy import Proxy
|
38
39
|
|
39
40
|
logger = logging.getLogger(__name__)
|
40
41
|
|
41
42
|
|
42
43
|
class Dev(Proxy):
|
44
|
+
"""All the development views."""
|
43
45
|
|
44
46
|
THEME_RE = re.compile(r"/theme/.*$")
|
45
47
|
|
46
|
-
def __init__(self, request):
|
48
|
+
def __init__(self, request: pyramid.request.Request):
|
47
49
|
super().__init__(request)
|
48
50
|
self.dev_url = self.request.registry.settings["devserver_url"]
|
49
51
|
|
50
|
-
@view_config(route_name="dev")
|
51
|
-
def dev(self):
|
52
|
+
@view_config(route_name="dev") # type: ignore
|
53
|
+
def dev(self) -> pyramid.response.Response:
|
52
54
|
path = self.THEME_RE.sub("", self.request.path_info)
|
53
55
|
if self.request.path.endswith("/dynamic.js"):
|
54
56
|
return HTTPFound(location=self.request.route_url("dynamic", _query=self.request.params))
|
55
|
-
return self._proxy_response("dev", "{
|
57
|
+
return self._proxy_response("dev", Url(f"{self.dev_url.rstrip('/')}/{path.lstrip('/')}"))
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2018-2021, Camptocamp SA
|
1
|
+
# Copyright (c) 2018-2025, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -30,8 +28,9 @@
|
|
30
28
|
|
31
29
|
import re
|
32
30
|
import urllib.parse
|
33
|
-
from typing import Dict, List, Union
|
31
|
+
from typing import Any, Dict, List, Union, cast
|
34
32
|
|
33
|
+
import pyramid.request
|
35
34
|
from pyramid.httpexceptions import HTTPNotFound
|
36
35
|
from pyramid.view import view_config
|
37
36
|
from sqlalchemy import func
|
@@ -39,22 +38,25 @@ from sqlalchemy import func
|
|
39
38
|
from c2cgeoportal_commons import models
|
40
39
|
from c2cgeoportal_commons.models import main
|
41
40
|
from c2cgeoportal_geoportal.lib.cacheversion import get_cache_version
|
42
|
-
from c2cgeoportal_geoportal.lib.caching import
|
41
|
+
from c2cgeoportal_geoportal.lib.caching import get_region
|
42
|
+
from c2cgeoportal_geoportal.lib.common_headers import Cache, set_common_headers
|
43
43
|
|
44
44
|
CACHE_REGION = get_region("std")
|
45
45
|
|
46
46
|
|
47
47
|
class DynamicView:
|
48
|
-
|
48
|
+
"""The dynamic vies that provide the configuration of the client application."""
|
49
|
+
|
50
|
+
def __init__(self, request: pyramid.request.Request):
|
49
51
|
self.request = request
|
50
52
|
self.settings = request.registry.settings
|
51
53
|
self.interfaces_config = self.settings["interfaces_config"]
|
52
54
|
|
53
|
-
def get(self, value, interface):
|
54
|
-
return self.interfaces_config.get(interface, {}).get(value, {})
|
55
|
+
def get(self, value: Dict[str, Any], interface: str) -> Dict[str, Any]:
|
56
|
+
return cast(Dict[str, Any], self.interfaces_config.get(interface, {}).get(value, {}))
|
55
57
|
|
56
|
-
@CACHE_REGION.cache_on_arguments()
|
57
|
-
def _fulltextsearch_groups(self)
|
58
|
+
@CACHE_REGION.cache_on_arguments() # type: ignore
|
59
|
+
def _fulltextsearch_groups(self) -> List[str]:
|
58
60
|
return [
|
59
61
|
group[0]
|
60
62
|
for group in models.DBSession.query(func.distinct(main.FullTextSearch.layer_name))
|
@@ -62,11 +64,30 @@ class DynamicView:
|
|
62
64
|
.all()
|
63
65
|
]
|
64
66
|
|
65
|
-
def _interface(
|
67
|
+
def _interface(
|
68
|
+
self,
|
69
|
+
interface_config: Dict[str, Any],
|
70
|
+
interface_name: str,
|
71
|
+
original_interface_name: str,
|
72
|
+
dynamic: Dict[str, Any],
|
73
|
+
) -> Dict[str, Any]:
|
74
|
+
"""
|
75
|
+
Get the interface configuration.
|
76
|
+
|
77
|
+
Arguments:
|
78
|
+
|
79
|
+
interface_config: Current interface configuration
|
80
|
+
interface_name: Interface name (we use in the configuration)
|
81
|
+
original_interface_name: Original interface name (directly for the query string)
|
82
|
+
dynamic: The values that's dynamically generated
|
83
|
+
"""
|
66
84
|
|
67
85
|
if "extends" in interface_config:
|
68
86
|
constants = self._interface(
|
69
|
-
self.interfaces_config[interface_config["extends"]],
|
87
|
+
self.interfaces_config[interface_config["extends"]],
|
88
|
+
interface_name,
|
89
|
+
original_interface_name,
|
90
|
+
dynamic,
|
70
91
|
)
|
71
92
|
else:
|
72
93
|
constants = {}
|
@@ -87,7 +108,7 @@ class DynamicView:
|
|
87
108
|
)
|
88
109
|
|
89
110
|
for constant, config in interface_config.get("routes", {}).items():
|
90
|
-
route_name =
|
111
|
+
route_name = original_interface_name if config.get("currentInterface", False) else config["name"]
|
91
112
|
params: Dict[str, str] = {}
|
92
113
|
params.update(config.get("params", {}))
|
93
114
|
for name, dyn in config.get("dynamic_params", {}).items():
|
@@ -98,14 +119,29 @@ class DynamicView:
|
|
98
119
|
|
99
120
|
return constants
|
100
121
|
|
101
|
-
@view_config(route_name="dynamic", renderer="json")
|
102
|
-
def dynamic(self):
|
103
|
-
|
122
|
+
@view_config(route_name="dynamic", renderer="json") # type: ignore
|
123
|
+
def dynamic(self) -> Dict[str, Any]:
|
124
|
+
self.request.response.headers["Vary"] = "Host"
|
125
|
+
original_interface_name = self.request.params.get("interface")
|
126
|
+
interface_name = self.request.get_organization_interface(original_interface_name)
|
104
127
|
|
105
128
|
if interface_name not in self.interfaces_config:
|
106
129
|
raise HTTPNotFound("Interface {} doesn't exists in the 'interfaces_config'.")
|
107
130
|
|
108
131
|
interface_config = self.interfaces_config[interface_name]
|
132
|
+
lang_urls_suffix = interface_config.get("lang_urls_suffix", "")
|
133
|
+
|
134
|
+
i18next_configuration = self.settings.get("i18next", {})
|
135
|
+
i18next_configuration.setdefault("backend", {})
|
136
|
+
if "loadPath" not in i18next_configuration["backend"]:
|
137
|
+
path: List[str] = [
|
138
|
+
self.request.route_url("base").rstrip("/"),
|
139
|
+
"static-{{ns}}",
|
140
|
+
get_cache_version(),
|
141
|
+
"locales",
|
142
|
+
"{{lng}}.json",
|
143
|
+
]
|
144
|
+
i18next_configuration["backend"]["loadPath"] = "/".join(path)
|
109
145
|
|
110
146
|
dynamic = {
|
111
147
|
"interface": interface_name,
|
@@ -113,14 +149,15 @@ class DynamicView:
|
|
113
149
|
"two_factor": self.request.registry.settings.get("authentication", {}).get("two_factor", False),
|
114
150
|
"lang_urls": {
|
115
151
|
lang: self.request.static_url(
|
116
|
-
"/etc/geomapfish/static/{lang}.json"
|
152
|
+
f"/etc/geomapfish/static/{lang}{lang_urls_suffix}.json",
|
117
153
|
)
|
118
154
|
for lang in self.request.registry.settings["available_locale_names"]
|
119
155
|
},
|
156
|
+
"i18next_configuration": i18next_configuration,
|
120
157
|
"fulltextsearch_groups": self._fulltextsearch_groups(),
|
121
158
|
}
|
122
159
|
|
123
|
-
constants = self._interface(interface_config, interface_name, dynamic)
|
160
|
+
constants = self._interface(interface_config, interface_name, original_interface_name, dynamic)
|
124
161
|
|
125
162
|
do_redirect = False
|
126
163
|
url = None
|
@@ -159,5 +196,5 @@ class DynamicView:
|
|
159
196
|
else:
|
160
197
|
constants["redirectUrl"] = no_redirect_url
|
161
198
|
|
162
|
-
set_common_headers(self.request, "dynamic",
|
199
|
+
set_common_headers(self.request, "dynamic", Cache.PUBLIC_NO)
|
163
200
|
return {"constants": constants, "doRedirect": do_redirect, "redirectUrl": url}
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -28,52 +26,115 @@
|
|
28
26
|
# either expressed or implied, of the FreeBSD Project.
|
29
27
|
|
30
28
|
|
29
|
+
import glob
|
31
30
|
import logging
|
32
|
-
import
|
33
|
-
from typing import Dict, Set, Tuple # noqa # pylint: disable=unused-import
|
31
|
+
from typing import Any, Dict, List, Optional
|
34
32
|
|
33
|
+
import pyramid.request
|
35
34
|
from pyramid.i18n import TranslationStringFactory
|
36
35
|
from pyramid.view import view_config
|
37
36
|
|
38
|
-
from c2cgeoportal_geoportal.lib.caching import
|
37
|
+
from c2cgeoportal_geoportal.lib.caching import get_region
|
38
|
+
from c2cgeoportal_geoportal.lib.common_headers import Cache, set_common_headers
|
39
39
|
|
40
40
|
_ = TranslationStringFactory("c2cgeoportal")
|
41
41
|
LOG = logging.getLogger(__name__)
|
42
|
+
CACHE_REGION = get_region("std")
|
42
43
|
|
43
44
|
|
44
45
|
class Entry:
|
45
|
-
|
46
|
+
"""All the entry points views."""
|
47
|
+
|
48
|
+
def __init__(self, request: pyramid.request.Request):
|
46
49
|
self.request = request
|
47
50
|
|
48
|
-
@view_config(route_name="testi18n", renderer="testi18n.html")
|
49
|
-
def testi18n(self)
|
51
|
+
@view_config(route_name="testi18n", renderer="testi18n.html") # type: ignore
|
52
|
+
def testi18n(self) -> Dict[str, Any]:
|
50
53
|
_ = self.request.translate
|
51
54
|
return {"title": _("title i18n")}
|
52
55
|
|
53
|
-
def get_ngeo_index_vars(self):
|
54
|
-
set_common_headers(self.request, "index",
|
56
|
+
def get_ngeo_index_vars(self) -> Dict[str, Any]:
|
57
|
+
set_common_headers(self.request, "index", Cache.PUBLIC_NO, content_type="text/html")
|
58
|
+
# Force urllogin to be converted to cookie when requesting the main HTML page
|
59
|
+
self.request.user # pylint: disable=pointless-statement
|
55
60
|
return {}
|
56
61
|
|
57
|
-
|
58
|
-
|
62
|
+
@staticmethod
|
63
|
+
@CACHE_REGION.cache_on_arguments() # type: ignore
|
64
|
+
def get_apijs(api_name: Optional[str]) -> str:
|
65
|
+
with open("/etc/static-ngeo/api.js", encoding="utf-8") as api_file:
|
66
|
+
api = api_file.read().split("\n")
|
67
|
+
sourcemap = api.pop(-1)
|
68
|
+
if api_name:
|
69
|
+
api += [
|
70
|
+
f"if (window.{api_name} === undefined && window.geomapfishapp) {{",
|
71
|
+
f" window.{api_name} = window.geomapfishapp;",
|
72
|
+
"}",
|
73
|
+
]
|
74
|
+
api.append(sourcemap)
|
75
|
+
|
76
|
+
return "\n".join(api)
|
77
|
+
|
78
|
+
@view_config(route_name="apijs") # type: ignore
|
79
|
+
def apijs(self) -> pyramid.response.Response:
|
80
|
+
self.request.response.text = self.get_apijs(self.request.registry.settings["api"].get("name"))
|
81
|
+
set_common_headers(self.request, "api", Cache.PUBLIC, content_type="application/javascript")
|
82
|
+
return self.request.response
|
83
|
+
|
84
|
+
def favicon(self) -> Dict[str, Any]:
|
85
|
+
set_common_headers(self.request, "index", Cache.PUBLIC, content_type="image/vnd.microsoft.icon")
|
59
86
|
return {}
|
60
87
|
|
61
|
-
def
|
62
|
-
set_common_headers(self.request, "index",
|
88
|
+
def robot_txt(self) -> Dict[str, Any]:
|
89
|
+
set_common_headers(self.request, "index", Cache.PUBLIC, content_type="text/plain")
|
63
90
|
return {}
|
64
91
|
|
65
|
-
def
|
66
|
-
set_common_headers(self.request, "
|
92
|
+
def apijsmap(self) -> Dict[str, Any]:
|
93
|
+
set_common_headers(self.request, "api", Cache.PUBLIC, content_type="application/octet-stream")
|
67
94
|
return {}
|
68
95
|
|
69
|
-
def
|
70
|
-
set_common_headers(self.request, "api",
|
96
|
+
def apicss(self) -> Dict[str, Any]:
|
97
|
+
set_common_headers(self.request, "api", Cache.PUBLIC, content_type="text/css")
|
71
98
|
return {}
|
72
99
|
|
73
|
-
def
|
74
|
-
set_common_headers(self.request, "
|
100
|
+
def apihelp(self) -> Dict[str, Any]:
|
101
|
+
set_common_headers(self.request, "apihelp", Cache.PUBLIC)
|
75
102
|
return {}
|
76
103
|
|
77
|
-
|
78
|
-
|
79
|
-
|
104
|
+
|
105
|
+
def _get_ngeo_resources(pattern: str) -> List[str]:
|
106
|
+
"""Return the list of ngeo dist files matching the pattern."""
|
107
|
+
return glob.glob(f"/opt/c2cgeoportal/geoportal/node_modules/ngeo/dist/{pattern}")
|
108
|
+
|
109
|
+
|
110
|
+
def canvas_view(request: pyramid.request.Request, interface_config: Dict[str, Any]) -> Dict[str, Any]:
|
111
|
+
"""Get view used as entry point of a canvas interface."""
|
112
|
+
|
113
|
+
js_files = _get_ngeo_resources(f"{interface_config.get('layout', interface_config['name'])}*.js")
|
114
|
+
css_files = _get_ngeo_resources(f"{interface_config.get('layout', interface_config['name'])}*.css")
|
115
|
+
css = "\n ".join(
|
116
|
+
[
|
117
|
+
f'<link href="{request.static_url(css)}" rel="stylesheet" crossorigin="anonymous">'
|
118
|
+
for css in css_files
|
119
|
+
]
|
120
|
+
)
|
121
|
+
|
122
|
+
set_common_headers(request, "index", Cache.PUBLIC_NO, content_type="text/html")
|
123
|
+
|
124
|
+
spinner = ""
|
125
|
+
spinner_filenames = _get_ngeo_resources("spinner*.svg")
|
126
|
+
if spinner_filenames:
|
127
|
+
with open(spinner_filenames[0], encoding="utf-8") as spinner_file:
|
128
|
+
spinner = spinner_file.read()
|
129
|
+
|
130
|
+
return {
|
131
|
+
"request": request,
|
132
|
+
"header": f"""
|
133
|
+
<meta name="dynamicUrl" content="{request.route_url("dynamic")}">
|
134
|
+
<meta name="interface" content="{interface_config['name']}">
|
135
|
+
{css}""",
|
136
|
+
"footer": "\n ".join(
|
137
|
+
[f'<script src="{request.static_url(js)}" crossorigin="anonymous"></script>' for js in js_files]
|
138
|
+
),
|
139
|
+
"spinner": spinner,
|
140
|
+
}
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2021, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -29,7 +27,9 @@
|
|
29
27
|
|
30
28
|
|
31
29
|
import re
|
30
|
+
from typing import cast
|
32
31
|
|
32
|
+
import pyramid.request
|
33
33
|
from geoalchemy2.shape import to_shape
|
34
34
|
from geojson import Feature, FeatureCollection
|
35
35
|
from pyramid.httpexceptions import HTTPBadRequest, HTTPInternalServerError
|
@@ -39,7 +39,8 @@ from sqlalchemy import and_, desc, func, or_
|
|
39
39
|
from c2cgeoportal_commons.models import DBSession
|
40
40
|
from c2cgeoportal_commons.models.main import FullTextSearch, Interface
|
41
41
|
from c2cgeoportal_geoportal import locale_negotiator
|
42
|
-
from c2cgeoportal_geoportal.lib.caching import
|
42
|
+
from c2cgeoportal_geoportal.lib.caching import get_region
|
43
|
+
from c2cgeoportal_geoportal.lib.common_headers import Cache, set_common_headers
|
43
44
|
from c2cgeoportal_geoportal.lib.fulltextsearch import Normalize
|
44
45
|
|
45
46
|
CACHE_REGION = get_region("std")
|
@@ -48,30 +49,32 @@ IGNORED_STARTUP_CHARS_RE = re.compile(r"^[']*")
|
|
48
49
|
|
49
50
|
|
50
51
|
class FullTextSearchView:
|
51
|
-
|
52
|
+
"""All the full-text search view."""
|
53
|
+
|
54
|
+
def __init__(self, request: pyramid.request.Request):
|
52
55
|
self.request = request
|
53
|
-
set_common_headers(request, "fulltextsearch",
|
56
|
+
set_common_headers(request, "fulltextsearch", Cache.PUBLIC_NO)
|
54
57
|
self.settings = request.registry.settings.get("fulltextsearch", {})
|
55
58
|
self.languages = self.settings.get("languages", {})
|
56
|
-
self.
|
59
|
+
self.fts_normalizer = Normalize(self.settings)
|
57
60
|
|
58
61
|
@staticmethod
|
59
|
-
@CACHE_REGION.cache_on_arguments()
|
60
|
-
def _get_interface_id(interface):
|
61
|
-
return DBSession.query(Interface).filter_by(name=interface).one().id
|
62
|
+
@CACHE_REGION.cache_on_arguments() # type: ignore
|
63
|
+
def _get_interface_id(interface: str) -> int:
|
64
|
+
return cast(int, DBSession.query(Interface).filter_by(name=interface).one().id)
|
62
65
|
|
63
|
-
@view_config(route_name="fulltextsearch", renderer="geojson")
|
64
|
-
def fulltextsearch(self):
|
66
|
+
@view_config(route_name="fulltextsearch", renderer="geojson") # type: ignore
|
67
|
+
def fulltextsearch(self) -> FeatureCollection:
|
65
68
|
lang = locale_negotiator(self.request)
|
66
69
|
|
67
70
|
try:
|
68
71
|
language = self.languages[lang]
|
69
72
|
except KeyError:
|
70
|
-
return HTTPInternalServerError(detail="{
|
73
|
+
return HTTPInternalServerError(detail=f"{lang!s} not defined in languages")
|
71
74
|
|
72
75
|
if "query" not in self.request.params:
|
73
76
|
return HTTPBadRequest(detail="no query")
|
74
|
-
terms = self.
|
77
|
+
terms = self.fts_normalizer(self.request.params.get("query"))
|
75
78
|
|
76
79
|
maxlimit = self.settings.get("maxlimit", 200)
|
77
80
|
|
@@ -79,15 +82,13 @@ class FullTextSearchView:
|
|
79
82
|
limit = int(self.request.params.get("limit", self.settings.get("defaultlimit", 30)))
|
80
83
|
except ValueError:
|
81
84
|
return HTTPBadRequest(detail="limit value is incorrect")
|
82
|
-
|
83
|
-
limit = maxlimit
|
85
|
+
limit = min(limit, maxlimit)
|
84
86
|
|
85
87
|
try:
|
86
88
|
partitionlimit = int(self.request.params.get("partitionlimit", 0))
|
87
89
|
except ValueError:
|
88
90
|
return HTTPBadRequest(detail="partitionlimit value is incorrect")
|
89
|
-
|
90
|
-
partitionlimit = maxlimit
|
91
|
+
partitionlimit = min(partitionlimit, maxlimit)
|
91
92
|
|
92
93
|
terms_array = [
|
93
94
|
IGNORED_STARTUP_CHARS_RE.sub("", elem) for elem in IGNORED_CHARS_RE.sub(" ", terms).split(" ")
|
@@ -144,21 +145,26 @@ class FullTextSearchView:
|
|
144
145
|
.over(partition_by=FullTextSearch.layer_name, order_by=(desc(rank), FullTextSearch.label))
|
145
146
|
.label("row_number")
|
146
147
|
)
|
147
|
-
|
148
|
+
sub_query = DBSession.query(FullTextSearch).add_columns(row_number).filter(_filter).subquery()
|
148
149
|
query = DBSession.query(
|
149
|
-
|
150
|
+
sub_query.c.id,
|
151
|
+
sub_query.c.label,
|
152
|
+
sub_query.c.params,
|
153
|
+
sub_query.c.layer_name,
|
154
|
+
sub_query.c.the_geom,
|
155
|
+
sub_query.c.actions,
|
150
156
|
)
|
151
|
-
query = query.filter(
|
157
|
+
query = query.filter(sub_query.c.row_number <= partitionlimit)
|
152
158
|
else:
|
153
159
|
query = DBSession.query(FullTextSearch).filter(_filter)
|
154
160
|
query = query.order_by(desc(rank))
|
155
161
|
query = query.order_by(FullTextSearch.label)
|
156
162
|
|
157
163
|
query = query.limit(limit)
|
158
|
-
|
164
|
+
objects = query.all()
|
159
165
|
|
160
166
|
features = []
|
161
|
-
for o in
|
167
|
+
for o in objects:
|
162
168
|
properties = {"label": o.label}
|
163
169
|
if o.layer_name is not None:
|
164
170
|
properties["layer_name"] = o.layer_name
|
@@ -1,6 +1,4 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (c) 2011-2020, Camptocamp SA
|
1
|
+
# Copyright (c) 2011-2023, Camptocamp SA
|
4
2
|
# All rights reserved.
|
5
3
|
|
6
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -28,28 +26,38 @@
|
|
28
26
|
# either expressed or implied, of the FreeBSD Project.
|
29
27
|
|
30
28
|
|
29
|
+
from typing import Optional
|
30
|
+
|
31
|
+
import pyramid.request
|
31
32
|
from geoalchemy2.shape import from_shape, to_shape
|
32
33
|
from geojson import loads
|
33
34
|
from pyramid.httpexceptions import HTTPBadRequest
|
34
35
|
from pyramid.view import view_config
|
35
|
-
from shapely.geometry import
|
36
|
+
from shapely.geometry import shape
|
37
|
+
from shapely.geometry.base import BaseGeometry
|
36
38
|
from sqlalchemy import func
|
37
39
|
|
38
40
|
from c2cgeoportal_commons.models import DBSession
|
39
41
|
|
40
42
|
|
41
43
|
class GeometryProcessing:
|
42
|
-
|
44
|
+
"""
|
45
|
+
View used to provide processing on a geometry.
|
46
|
+
|
47
|
+
Currently only difference between geometries.
|
48
|
+
"""
|
49
|
+
|
50
|
+
def __init__(self, request: pyramid.request.Request):
|
43
51
|
self.request = request
|
44
52
|
|
45
|
-
@view_config(route_name="difference", renderer="geojson")
|
46
|
-
def difference(self):
|
53
|
+
@view_config(route_name="difference", renderer="geojson") # type: ignore
|
54
|
+
def difference(self) -> Optional[BaseGeometry]:
|
47
55
|
body = loads(self.request.body)
|
48
56
|
if (
|
49
57
|
"geometries" not in body
|
50
58
|
or not isinstance(body["geometries"], list)
|
51
59
|
or len(body["geometries"]) != 2
|
52
|
-
):
|
60
|
+
):
|
53
61
|
raise HTTPBadRequest(
|
54
62
|
"""Wrong body, it should be like that:
|
55
63
|
{
|
@@ -61,7 +69,7 @@ class GeometryProcessing:
|
|
61
69
|
return to_shape(
|
62
70
|
DBSession.query(
|
63
71
|
func.ST_Difference(
|
64
|
-
from_shape(
|
72
|
+
from_shape(shape(body["geometries"][0])), from_shape(shape(body["geometries"][1]))
|
65
73
|
)
|
66
74
|
).scalar()
|
67
75
|
)
|