c2cgeoportal-geoportal 2.7.1.156__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 +24 -14
- c2cgeoportal_geoportal/lib/authentication.py +10 -14
- c2cgeoportal_geoportal/lib/caching.py +8 -6
- c2cgeoportal_geoportal/lib/checker.py +10 -6
- c2cgeoportal_geoportal/lib/common_headers.py +5 -8
- c2cgeoportal_geoportal/lib/dbreflection.py +8 -8
- c2cgeoportal_geoportal/lib/filter_capabilities.py +5 -1
- c2cgeoportal_geoportal/lib/lingua_extractor.py +11 -12
- c2cgeoportal_geoportal/lib/loader.py +1 -1
- c2cgeoportal_geoportal/lib/oauth2.py +217 -100
- c2cgeoportal_geoportal/lib/wmstparsing.py +8 -12
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/Dockerfile +9 -11
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/development.ini +1 -1
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +0 -2
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +1 -1
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +6 -4
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js +1 -3
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.commons.js +1 -0
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +1 -6
- c2cgeoportal_geoportal/scaffolds/advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile +0 -20
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +20 -6
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +4 -3
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +22 -22
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +58 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +48 -24
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +2 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +26 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-lib.yaml +53 -26
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +23 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +0 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.yaml +3 -3
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +21 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +9 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/vars.yaml +38 -14
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/data/Readme.txt +2 -2
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +15 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.map.tmpl +2 -3
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Landscape.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Portrait.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Landscape.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Portrait.jrxml +5 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/config.yaml.tmpl +6 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/pyproject.toml +4 -0
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/run_alembic.sh +3 -5
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +1 -1
- c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +2 -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/update/{{cookiecutter.project}}/.upgrade.yaml +2 -132
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +210 -1097
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_config-schema.yaml +17 -15
- c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_vars.yaml +46 -2
- c2cgeoportal_geoportal/scripts/c2cupgrade.py +1 -2
- c2cgeoportal_geoportal/scripts/pcreate.py +8 -10
- c2cgeoportal_geoportal/scripts/theme2fts.py +58 -3
- c2cgeoportal_geoportal/views/__init__.py +1 -3
- c2cgeoportal_geoportal/views/dynamic.py +1 -1
- c2cgeoportal_geoportal/views/entry.py +2 -10
- c2cgeoportal_geoportal/views/fulltextsearch.py +1 -1
- c2cgeoportal_geoportal/views/geometry_processing.py +3 -3
- c2cgeoportal_geoportal/views/layers.py +10 -11
- c2cgeoportal_geoportal/views/login.py +63 -8
- c2cgeoportal_geoportal/views/mapserverproxy.py +2 -3
- c2cgeoportal_geoportal/views/ogcproxy.py +6 -2
- c2cgeoportal_geoportal/views/pdfreport.py +4 -4
- c2cgeoportal_geoportal/views/printproxy.py +2 -2
- c2cgeoportal_geoportal/views/profile.py +1 -1
- c2cgeoportal_geoportal/views/proxy.py +2 -4
- c2cgeoportal_geoportal/views/raster.py +2 -2
- c2cgeoportal_geoportal/views/resourceproxy.py +1 -1
- c2cgeoportal_geoportal/views/shortener.py +1 -2
- c2cgeoportal_geoportal/views/theme.py +97 -63
- c2cgeoportal_geoportal/views/tinyowsproxy.py +3 -12
- c2cgeoportal_geoportal/views/vector_tiles.py +1 -1
- {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/METADATA +21 -15
- {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/RECORD +96 -90
- {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/entry_points.txt +1 -0
- tests/__init__.py +3 -2
- tests/test_cachebuster.py +3 -3
- tests/test_caching.py +7 -7
- tests/test_checker.py +1 -1
- tests/test_decimaljson.py +1 -1
- tests/test_headerstween.py +1 -1
- tests/test_i18n.py +1 -1
- tests/test_init.py +14 -15
- tests/test_locale_negociator.py +4 -4
- tests/test_mapserverproxy_route_predicate.py +1 -2
- tests/test_raster.py +15 -15
- tests/test_wmstparsing.py +10 -10
- tests/xmlstr.py +1 -3
- c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tools/extract-messages.js +0 -41
- {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/WHEEL +0 -0
- {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.180.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
# This file should be used only on the test project in the c2cgeoportal CI
|
2
|
+
|
3
|
+
import re
|
4
|
+
|
5
|
+
import polib
|
6
|
+
import pytest
|
7
|
+
import requests
|
8
|
+
|
9
|
+
|
10
|
+
@pytest.mark.parametrize("test_number", [0, 1])
|
11
|
+
def test_po(test_number: int) -> None:
|
12
|
+
"""Tests that the generated pot files are identical between the command line and the view."""
|
13
|
+
del test_number
|
14
|
+
|
15
|
+
response = requests.get("https://front/locale.pot", verify=False, timeout=30) # nosec
|
16
|
+
assert response.status_code == 200, response.text
|
17
|
+
response_keys = {e.msgid for e in polib.pofile(response.text)}
|
18
|
+
|
19
|
+
with open(
|
20
|
+
"geoportal/{{cookiecutter.package}}_geoportal/locale/{{cookiecutter.package}}_geoportal-client.pot",
|
21
|
+
encoding="utf-8",
|
22
|
+
) as current_file:
|
23
|
+
current_content = current_file.read()
|
24
|
+
current_content_keys = {e.msgid for e in polib.pofile(current_content)}
|
25
|
+
|
26
|
+
if response_keys != current_content_keys:
|
27
|
+
assert response.text == current_content
|
28
|
+
|
29
|
+
|
30
|
+
@pytest.mark.parametrize("url", ["https://front/desktop_alt"])
|
31
|
+
def test_desktop_alt(url: str) -> None:
|
32
|
+
"""Tests the desktop alt page."""
|
33
|
+
response = requests.get(url, verify=False, timeout=30) # nosec
|
34
|
+
assert response.status_code == 200, response.text
|
35
|
+
|
36
|
+
assert re.search(
|
37
|
+
r'<script src="https?://front/static-ngeo-dist/desktop\..*\.js" crossorigin="anonymous"></script>',
|
38
|
+
response.text,
|
39
|
+
), response.text
|
40
|
+
assert re.search(r'<html lang="{{"{{mainCtrl.lang}}"}}" ', response.text), response.text
|
41
|
+
|
42
|
+
|
43
|
+
def test_enum() -> None:
|
44
|
+
"""Test the enumerations view"""
|
45
|
+
response = requests.get("https://front/layers/test/values/type", verify=False, timeout=30) # nosec
|
46
|
+
assert response.status_code == 200, response.text
|
47
|
+
|
48
|
+
assert response.json() == {"items": [{"value": "car"}, {"value": "train"}]}, response.text
|
c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_config-schema.yaml
CHANGED
@@ -44,6 +44,8 @@ mapping:
|
|
44
44
|
package:
|
45
45
|
type: str
|
46
46
|
required: True
|
47
|
+
main_ogc_server:
|
48
|
+
type: str
|
47
49
|
enable_admin_interface:
|
48
50
|
type: scalar
|
49
51
|
required: True
|
@@ -123,7 +125,7 @@ mapping:
|
|
123
125
|
required: True
|
124
126
|
type: map
|
125
127
|
mapping:
|
126
|
-
regex
|
128
|
+
regex;(.+):
|
127
129
|
type: map
|
128
130
|
mapping:
|
129
131
|
extends:
|
@@ -131,17 +133,17 @@ mapping:
|
|
131
133
|
constants:
|
132
134
|
type: map
|
133
135
|
mapping:
|
134
|
-
regex
|
136
|
+
regex;(.+):
|
135
137
|
type: any
|
136
138
|
dynamic_constants:
|
137
139
|
type: map
|
138
140
|
mapping:
|
139
|
-
regex
|
141
|
+
regex;(.+):
|
140
142
|
type: str
|
141
143
|
routes:
|
142
144
|
type: map
|
143
145
|
mapping:
|
144
|
-
regex
|
146
|
+
regex;(.+):
|
145
147
|
type: map
|
146
148
|
mapping:
|
147
149
|
name:
|
@@ -155,22 +157,22 @@ mapping:
|
|
155
157
|
kw:
|
156
158
|
type: map
|
157
159
|
mapping:
|
158
|
-
regex
|
160
|
+
regex;(.+):
|
159
161
|
type: str
|
160
162
|
params:
|
161
163
|
type: map
|
162
164
|
mapping:
|
163
|
-
regex
|
165
|
+
regex;(.+):
|
164
166
|
type: text
|
165
167
|
dynamic_params:
|
166
168
|
type: map
|
167
169
|
mapping:
|
168
|
-
regex
|
170
|
+
regex;(.+):
|
169
171
|
type: str
|
170
172
|
static:
|
171
173
|
type: map
|
172
174
|
mapping:
|
173
|
-
regex
|
175
|
+
regex;(.+):
|
174
176
|
type: map
|
175
177
|
mapping:
|
176
178
|
name:
|
@@ -227,7 +229,7 @@ mapping:
|
|
227
229
|
type: map
|
228
230
|
required: True
|
229
231
|
mapping:
|
230
|
-
regex
|
232
|
+
regex;(.+):
|
231
233
|
type: str
|
232
234
|
headers:
|
233
235
|
type: map
|
@@ -253,7 +255,7 @@ mapping:
|
|
253
255
|
headers:
|
254
256
|
type: map
|
255
257
|
mapping:
|
256
|
-
regex
|
258
|
+
regex;(.+):
|
257
259
|
type: str
|
258
260
|
index: *header
|
259
261
|
dynamic: *header
|
@@ -283,7 +285,7 @@ mapping:
|
|
283
285
|
type: map
|
284
286
|
required: True
|
285
287
|
mapping:
|
286
|
-
regex
|
288
|
+
regex;(.+):
|
287
289
|
type: map
|
288
290
|
mapping:
|
289
291
|
backend:
|
@@ -292,7 +294,7 @@ mapping:
|
|
292
294
|
arguments:
|
293
295
|
type: map
|
294
296
|
mapping:
|
295
|
-
regex
|
297
|
+
regex;(.+):
|
296
298
|
type: any
|
297
299
|
admin_interface:
|
298
300
|
type: map
|
@@ -308,7 +310,7 @@ mapping:
|
|
308
310
|
sequence:
|
309
311
|
- type: map
|
310
312
|
mapping:
|
311
|
-
regex
|
313
|
+
regex;(.+):
|
312
314
|
type: any
|
313
315
|
fitSource:
|
314
316
|
type: bool
|
@@ -344,7 +346,7 @@ mapping:
|
|
344
346
|
type: str
|
345
347
|
zoom:
|
346
348
|
type: int
|
347
|
-
regex
|
349
|
+
regex;(.+):
|
348
350
|
type: any
|
349
351
|
available_metadata:
|
350
352
|
type: seq
|
@@ -417,7 +419,7 @@ mapping:
|
|
417
419
|
required: True
|
418
420
|
map:
|
419
421
|
<<: *map_config
|
420
|
-
regex
|
422
|
+
regex;(.+):
|
421
423
|
type: any
|
422
424
|
|
423
425
|
layers:
|
@@ -51,6 +51,7 @@ vars:
|
|
51
51
|
ns:
|
52
52
|
- geomapfish
|
53
53
|
defaultNS: geomapfish
|
54
|
+
keySeparator: false
|
54
55
|
debug: false
|
55
56
|
detection:
|
56
57
|
order:
|
@@ -210,7 +211,7 @@ vars:
|
|
210
211
|
gmfBackgroundLayerSelectorOptions: {}
|
211
212
|
defaultTheme: Demo
|
212
213
|
defaultLang: en
|
213
|
-
gmfOptions:
|
214
|
+
gmfOptions: &gmfOptions
|
214
215
|
map: {}
|
215
216
|
view:
|
216
217
|
srid: '{srid}'
|
@@ -219,6 +220,7 @@ vars:
|
|
219
220
|
resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05]
|
220
221
|
extent: [2420000, 1030000, 2900000, 1350000]
|
221
222
|
constrainRotation: false
|
223
|
+
constrainResolution: true
|
222
224
|
gmfSearchOptions:
|
223
225
|
styles:
|
224
226
|
default:
|
@@ -297,6 +299,11 @@ vars:
|
|
297
299
|
width: 2
|
298
300
|
zoom:
|
299
301
|
autoRotate: False
|
302
|
+
gmfWMSSourceOptions:
|
303
|
+
# The default value is 1.5 but it add a slight blur on the layer,
|
304
|
+
# 1 is also possible but the application will do a getMap on all the pan.
|
305
|
+
ratio: 2
|
306
|
+
|
300
307
|
dynamic_constants:
|
301
308
|
interface: interface
|
302
309
|
cacheVersion: cache_version
|
@@ -343,6 +350,7 @@ vars:
|
|
343
350
|
redirect_interface: mobile
|
344
351
|
do_redirect: True
|
345
352
|
constants:
|
353
|
+
gmfOptions: *gmfOptions
|
346
354
|
ngeoProfileOptions: {}
|
347
355
|
ngeoStreetviewOptions:
|
348
356
|
viewer: 'mapillary'
|
@@ -363,7 +371,9 @@ vars:
|
|
363
371
|
LAYERFONTSIZE: '10'
|
364
372
|
ITEMFONTSIZE: '8'
|
365
373
|
hiddenAttributes:
|
374
|
+
- debug
|
366
375
|
- timezone
|
376
|
+
- username
|
367
377
|
gmfDisplayQueryGridOptions:
|
368
378
|
featuresStyle: *featureStyle
|
369
379
|
selectedFeatureStyle: *selectedFeatureStyle
|
@@ -392,15 +402,20 @@ vars:
|
|
392
402
|
radius: 3
|
393
403
|
gmfShareOptions:
|
394
404
|
enableEmail: True
|
405
|
+
gmfFitOptions:
|
406
|
+
# Padding (in pixels) to be correctly fitted inside the view. Values in the array are top, right, bottom and left padding.
|
407
|
+
padding: [50, 10, 50, 50]
|
395
408
|
routes:
|
396
409
|
gmfProfileJsonUrl:
|
397
410
|
name: profile.json
|
398
411
|
gmfPrintUrl:
|
399
412
|
name: printproxy
|
413
|
+
|
400
414
|
mobile:
|
401
415
|
extends: default
|
402
416
|
redirect_interface: desktop
|
403
417
|
constants:
|
418
|
+
gmfOptions: *gmfOptions
|
404
419
|
gmfMobileMeasureAreaOptions:
|
405
420
|
precision: 2
|
406
421
|
sketchStyle: &mobileMeasureStyle
|
@@ -440,10 +455,19 @@ vars:
|
|
440
455
|
radius: 8
|
441
456
|
radius2: 0
|
442
457
|
angle: 0
|
458
|
+
gmfFitOptions:
|
459
|
+
# Padding (in pixels) to be correctly fitted inside the view. Values in the array are top, right, bottom and left padding.
|
460
|
+
padding: [60, 60, 42, 10]
|
461
|
+
|
443
462
|
iframe_api:
|
444
463
|
extends: default
|
445
464
|
constants:
|
465
|
+
gmfOptions: *gmfOptions
|
446
466
|
gmfSearchGroups: []
|
467
|
+
gmfFitOptions:
|
468
|
+
# Padding (in pixels) to be correctly fitted inside the view. Values in the array are top, right, bottom and left padding.
|
469
|
+
padding: [20, 20, 20, 20]
|
470
|
+
|
447
471
|
api:
|
448
472
|
constants:
|
449
473
|
projections: *projections
|
@@ -469,15 +493,19 @@ vars:
|
|
469
493
|
cache:
|
470
494
|
std:
|
471
495
|
backend: c2cgeoportal.hybridsentinel
|
472
|
-
arguments:
|
496
|
+
arguments: &redis-cache-arguments
|
473
497
|
lock_timeout: '{REDIS_LOCK_TIMEOUT}' # seconds
|
474
498
|
redis_expiration_time: '{REDIS_EXPIRATION_TIME}' # seconds
|
475
499
|
distributed_lock: True
|
500
|
+
thread_local_lock: False
|
476
501
|
service_name: '{REDIS_SERVICENAME}'
|
477
502
|
socket_timeout: '{REDIS_TIMEOUT}' # seconds
|
478
503
|
db: 0
|
479
504
|
obj:
|
480
505
|
backend: dogpile.cache.memory
|
506
|
+
ogc-server:
|
507
|
+
backend: c2cgeoportal.hybridsentinel
|
508
|
+
arguments: *redis-cache-arguments
|
481
509
|
|
482
510
|
admin_interface:
|
483
511
|
layer_tree_max_nodes: 1000
|
@@ -493,6 +521,18 @@ vars:
|
|
493
521
|
tree item will match when searching for the search aliases.
|
494
522
|
relevant_for:
|
495
523
|
- treeitem
|
524
|
+
- name: searchLabelPattern
|
525
|
+
description: >
|
526
|
+
Template string for the label of tree items in the search results, for example: "{name} ({theme})"
|
527
|
+
Supported parameters:
|
528
|
+
<ul>
|
529
|
+
<li>name (name of the tree item)</li>
|
530
|
+
<li>parent (parent of the item, may be a group, a block or a theme)</li>
|
531
|
+
<li>block (name of the block to which the item belongs)</li>
|
532
|
+
<li>theme (name of the theme to which the item belongs)</li>
|
533
|
+
</ul>
|
534
|
+
relevant_for:
|
535
|
+
- treeitem
|
496
536
|
# Layers group
|
497
537
|
- name: exclusiveGroup
|
498
538
|
type: boolean
|
@@ -1313,6 +1353,10 @@ runtime_postprocess:
|
|
1313
1353
|
- cache.std.arguments.redis_expiration_time
|
1314
1354
|
- cache.std.arguments.socket_timeout
|
1315
1355
|
- cache.std.arguments.db
|
1356
|
+
- cache.ogc-server.arguments.lock_timeout
|
1357
|
+
- cache.ogc-server.arguments.redis_expiration_time
|
1358
|
+
- cache.ogc-server.arguments.socket_timeout
|
1359
|
+
- cache.ogc-server.arguments.db
|
1316
1360
|
- sqlalchemy\.pool_recycle
|
1317
1361
|
- sqlalchemy\.pool_size
|
1318
1362
|
- sqlalchemy\.max_overflow
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2014-
|
1
|
+
# Copyright (c) 2014-2023, Camptocamp SA
|
2
2
|
# All rights reserved.
|
3
3
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -247,7 +247,6 @@ class C2cUpgradeTool:
|
|
247
247
|
except ConnectionRefusedError as exception:
|
248
248
|
return False, "\n".join([f"Connection refused: {exception}", run_curl])
|
249
249
|
if resp.status_code < 200 or resp.status_code >= 300:
|
250
|
-
|
251
250
|
print(colorize("=============", Color.RED))
|
252
251
|
print(colorize("Checker error", Color.RED))
|
253
252
|
try:
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2021-
|
1
|
+
# Copyright (c) 2021-2023, Camptocamp SA
|
2
2
|
# All rights reserved.
|
3
3
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -183,9 +183,9 @@ class PCreateCommand:
|
|
183
183
|
}
|
184
184
|
context.update(self.read_project_file())
|
185
185
|
if os.environ.get("CI") == "true":
|
186
|
-
context[
|
187
|
-
"
|
188
|
-
|
186
|
+
context[ # nosec
|
187
|
+
"authtkt_secret"
|
188
|
+
] = "io7heoDui8xaikie1rushaeGeiph8Bequei6ohchaequob6viejei0xooWeuvohf"
|
189
189
|
|
190
190
|
self.get_var(context, "srid", "Spatial Reference System Identifier (e.g. 2056): ", int)
|
191
191
|
srid = cast(int, context["srid"])
|
@@ -193,12 +193,10 @@ class PCreateCommand:
|
|
193
193
|
self.get_var(
|
194
194
|
context,
|
195
195
|
"extent",
|
196
|
-
(
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
else f"Extent (minx miny maxx maxy): in EPSG: {srid} projection: "
|
201
|
-
),
|
196
|
+
f"Extent (minx miny maxx maxy): in EPSG: {srid} projection, default is "
|
197
|
+
f"[{extent[0]} {extent[1]} {extent[2]} {extent[3]}]: "
|
198
|
+
if extent
|
199
|
+
else f"Extent (minx miny maxx maxy): in EPSG: {srid} projection: ",
|
202
200
|
)
|
203
201
|
match = re.match(
|
204
202
|
r"([\d.]+)[,; ] *([\d.]+)[,; ] *([\d.]+)[,; ] *([\d.]+)",
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2014-
|
1
|
+
# Copyright (c) 2014-2023, Camptocamp SA
|
2
2
|
# All rights reserved.
|
3
3
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -30,7 +30,7 @@ import gettext
|
|
30
30
|
import os
|
31
31
|
import sys
|
32
32
|
from argparse import ArgumentParser, Namespace
|
33
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set
|
33
|
+
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Optional, Set
|
34
34
|
|
35
35
|
import pyramid.config
|
36
36
|
import transaction
|
@@ -190,7 +190,7 @@ class Import:
|
|
190
190
|
self.imported.add(key)
|
191
191
|
for lang in self.languages:
|
192
192
|
fts = FullTextSearch()
|
193
|
-
fts.label = self.
|
193
|
+
fts.label = self._render_label(item, lang)
|
194
194
|
fts.role = role
|
195
195
|
fts.interface = interface
|
196
196
|
fts.lang = lang
|
@@ -289,3 +289,58 @@ class Import:
|
|
289
289
|
self._add_fts(layer, interface, "add_layer", role)
|
290
290
|
|
291
291
|
return fill
|
292
|
+
|
293
|
+
def _render_label(
|
294
|
+
self,
|
295
|
+
item: "c2cgeoportal_commons.models.main.TreeItem",
|
296
|
+
lang: str,
|
297
|
+
) -> str:
|
298
|
+
patterns = item.get_metadata("searchLabelPattern")
|
299
|
+
if not patterns:
|
300
|
+
return self._[lang].gettext(item.name)
|
301
|
+
pattern = patterns[0]
|
302
|
+
assert isinstance(pattern.value, str)
|
303
|
+
tree_paths = list(self._get_paths(item))
|
304
|
+
# Remove paths where the last element isn't a theme
|
305
|
+
tree_paths = [p for p in tree_paths if p[-1].item_type == "theme"]
|
306
|
+
result = None
|
307
|
+
current_result = None
|
308
|
+
if tree_paths:
|
309
|
+
for path in tree_paths:
|
310
|
+
if len(path) == 2:
|
311
|
+
current_result = pattern.value.format(
|
312
|
+
name=self._[lang].gettext(item.name),
|
313
|
+
theme=self._[lang].gettext(path[-1].name),
|
314
|
+
parent=self._[lang].gettext(path[1].name),
|
315
|
+
)
|
316
|
+
elif len(path) > 2:
|
317
|
+
current_result = pattern.value.format(
|
318
|
+
name=self._[lang].gettext(item.name),
|
319
|
+
theme=self._[lang].gettext(path[-1].name),
|
320
|
+
parent=self._[lang].gettext(path[1].name),
|
321
|
+
block=self._[lang].gettext(path[-2].name),
|
322
|
+
)
|
323
|
+
if result and current_result != result:
|
324
|
+
sys.stderr.write(
|
325
|
+
f"WARNING: the item {item.name} (id: {item.id}) has a label pattern and inconsistent "
|
326
|
+
f"multiple parents\n"
|
327
|
+
)
|
328
|
+
return self._[lang].gettext(item.name)
|
329
|
+
result = current_result
|
330
|
+
return result or pattern.value.format(
|
331
|
+
name=self._[lang].gettext(item.name),
|
332
|
+
theme=self._[lang].gettext(item.name),
|
333
|
+
)
|
334
|
+
|
335
|
+
def _get_paths(
|
336
|
+
self,
|
337
|
+
item: "c2cgeoportal_commons.models.main.TreeItem",
|
338
|
+
) -> Iterator[List["c2cgeoportal_commons.models.main.TreeItem"]]:
|
339
|
+
if item is None:
|
340
|
+
return
|
341
|
+
if any(item.parents):
|
342
|
+
for parent in item.parents:
|
343
|
+
for path in self._get_paths(parent):
|
344
|
+
yield [item, *path]
|
345
|
+
else:
|
346
|
+
yield [item]
|
@@ -56,7 +56,7 @@ class DynamicView:
|
|
56
56
|
return cast(Dict[str, Any], self.interfaces_config.get(interface, {}).get(value, {}))
|
57
57
|
|
58
58
|
@CACHE_REGION.cache_on_arguments() # type: ignore
|
59
|
-
def _fulltextsearch_groups(self) -> List[str]:
|
59
|
+
def _fulltextsearch_groups(self) -> List[str]:
|
60
60
|
return [
|
61
61
|
group[0]
|
62
62
|
for group in models.DBSession.query(func.distinct(main.FullTextSearch.layer_name))
|
@@ -28,7 +28,6 @@
|
|
28
28
|
|
29
29
|
import glob
|
30
30
|
import logging
|
31
|
-
import os
|
32
31
|
from typing import Any, Dict, List, Optional
|
33
32
|
|
34
33
|
import pyramid.request
|
@@ -57,7 +56,7 @@ class Entry:
|
|
57
56
|
def get_ngeo_index_vars(self) -> Dict[str, Any]:
|
58
57
|
set_common_headers(self.request, "index", Cache.PUBLIC_NO, content_type="text/html")
|
59
58
|
# Force urllogin to be converted to cookie when requesting the main HTML page
|
60
|
-
self.request.user #
|
59
|
+
self.request.user # pylint: disable=pointless-statement
|
61
60
|
return {}
|
62
61
|
|
63
62
|
@staticmethod
|
@@ -105,14 +104,7 @@ class Entry:
|
|
105
104
|
|
106
105
|
def _get_ngeo_resources(pattern: str) -> List[str]:
|
107
106
|
"""Return the list of ngeo dist files matching the pattern."""
|
108
|
-
|
109
|
-
if not results:
|
110
|
-
LOG.error(
|
111
|
-
"No file found for pattern %s, in: [%s]",
|
112
|
-
pattern,
|
113
|
-
", ".join(os.listdir("/opt/c2cgeoportal/geoportal/node_modules/ngeo/dist/")),
|
114
|
-
)
|
115
|
-
return results
|
107
|
+
return glob.glob(f"/opt/c2cgeoportal/geoportal/node_modules/ngeo/dist/{pattern}")
|
116
108
|
|
117
109
|
|
118
110
|
def canvas_view(request: pyramid.request.Request, interface_config: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2011-
|
1
|
+
# Copyright (c) 2011-2023, Camptocamp SA
|
2
2
|
# All rights reserved.
|
3
3
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -33,7 +33,7 @@ from geoalchemy2.shape import from_shape, to_shape
|
|
33
33
|
from geojson import loads
|
34
34
|
from pyramid.httpexceptions import HTTPBadRequest
|
35
35
|
from pyramid.view import view_config
|
36
|
-
from shapely.geometry import
|
36
|
+
from shapely.geometry import shape
|
37
37
|
from shapely.geometry.base import BaseGeometry
|
38
38
|
from sqlalchemy import func
|
39
39
|
|
@@ -69,7 +69,7 @@ class GeometryProcessing:
|
|
69
69
|
return to_shape(
|
70
70
|
DBSession.query(
|
71
71
|
func.ST_Difference(
|
72
|
-
from_shape(
|
72
|
+
from_shape(shape(body["geometries"][0])), from_shape(shape(body["geometries"][1]))
|
73
73
|
)
|
74
74
|
).scalar()
|
75
75
|
)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (c) 2012-
|
1
|
+
# Copyright (c) 2012-2023, Camptocamp SA
|
2
2
|
# All rights reserved.
|
3
3
|
|
4
4
|
# Redistribution and use in source and binary forms, with or without
|
@@ -34,6 +34,7 @@ from typing import TYPE_CHECKING, Any, Dict, Generator, List, Optional, Set, Tup
|
|
34
34
|
import geojson.geometry
|
35
35
|
import pyramid.request
|
36
36
|
import pyramid.response
|
37
|
+
import shapely.geometry
|
37
38
|
import sqlalchemy.ext.declarative
|
38
39
|
from geoalchemy2 import Geometry
|
39
40
|
from geoalchemy2 import func as ga_func
|
@@ -49,8 +50,7 @@ from pyramid.httpexceptions import (
|
|
49
50
|
HTTPNotFound,
|
50
51
|
)
|
51
52
|
from pyramid.view import view_config
|
52
|
-
from shapely.
|
53
|
-
from shapely.geos import TopologicalError
|
53
|
+
from shapely.errors import TopologicalError
|
54
54
|
from shapely.ops import cascaded_union
|
55
55
|
from sqlalchemy import Enum, Numeric, String, Text, Unicode, UnicodeText, exc, func
|
56
56
|
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
|
@@ -190,7 +190,7 @@ class Layers:
|
|
190
190
|
|
191
191
|
feature = proto.read(self.request, filter=filter_)
|
192
192
|
if isinstance(feature, HTTPException):
|
193
|
-
raise feature
|
193
|
+
raise feature
|
194
194
|
return feature
|
195
195
|
|
196
196
|
@view_config(route_name="layers_read_many", renderer="geojson") # type: ignore
|
@@ -228,7 +228,7 @@ class Layers:
|
|
228
228
|
geom = feature.geometry
|
229
229
|
if not geom or isinstance(geom, geojson.geometry.Default):
|
230
230
|
return feature
|
231
|
-
shape =
|
231
|
+
shape = shapely.geometry.shape(geom)
|
232
232
|
srid = self._get_geom_col_info(layer)[1]
|
233
233
|
spatial_elt = from_shape(shape, srid=srid)
|
234
234
|
allowed = models.DBSession.query(func.count(RestrictionArea.id))
|
@@ -275,7 +275,7 @@ class Layers:
|
|
275
275
|
del obj # unused
|
276
276
|
geom = feature.geometry
|
277
277
|
if geom and not isinstance(geom, geojson.geometry.Default):
|
278
|
-
shape =
|
278
|
+
shape = shapely.geometry.shape(geom)
|
279
279
|
srid = self._get_geom_col_info(layer)[1]
|
280
280
|
spatial_elt = from_shape(shape, srid=srid)
|
281
281
|
allowed = models.DBSession.query(func.count(RestrictionArea.id))
|
@@ -298,7 +298,7 @@ class Layers:
|
|
298
298
|
try:
|
299
299
|
features = protocol.create(self.request)
|
300
300
|
if isinstance(features, HTTPException):
|
301
|
-
raise features
|
301
|
+
raise features
|
302
302
|
if features is not None:
|
303
303
|
for feature in features.features: # pylint: disable=no-member
|
304
304
|
self._log_last_update(layer, feature)
|
@@ -346,7 +346,7 @@ class Layers:
|
|
346
346
|
)
|
347
347
|
spatial_elt = None
|
348
348
|
if geom and not isinstance(geom, geojson.geometry.Default):
|
349
|
-
shape =
|
349
|
+
shape = shapely.geometry.shape(geom)
|
350
350
|
spatial_elt = from_shape(shape, srid=srid)
|
351
351
|
allowed = allowed.filter(
|
352
352
|
or_(RestrictionArea.area.is_(None), RestrictionArea.area.ST_Contains(spatial_elt))
|
@@ -439,7 +439,7 @@ class Layers:
|
|
439
439
|
protocol = self._get_protocol_for_layer(layer, before_delete=security_cb)
|
440
440
|
response = protocol.delete(self.request, feature_id)
|
441
441
|
if isinstance(response, HTTPException):
|
442
|
-
raise response
|
442
|
+
raise response
|
443
443
|
set_common_headers(self.request, "layers", Cache.PRIVATE_NO, response=response)
|
444
444
|
return response
|
445
445
|
|
@@ -506,7 +506,7 @@ def get_layer_class(
|
|
506
506
|
"""
|
507
507
|
Get the SQLAlchemy class to edit a GeoMapFish layer.
|
508
508
|
|
509
|
-
Arguments:
|
509
|
+
Keyword Arguments:
|
510
510
|
|
511
511
|
layer: The GeoMapFish layer
|
512
512
|
with_last_update_columns: False to just have a class to access to the table and be able to
|
@@ -584,7 +584,6 @@ def get_layer_metadata(layer: "main.Layer") -> List[ColumnProperties]:
|
|
584
584
|
|
585
585
|
for column_property in class_mapper(cls).iterate_properties:
|
586
586
|
if isinstance(column_property, ColumnProperty):
|
587
|
-
|
588
587
|
if len(column_property.columns) != 1:
|
589
588
|
raise NotImplementedError
|
590
589
|
|