0005-general-remove-is_using_postgresql-conditionals-6719.patch
tests/api/test_formdata.py | ||
---|---|---|
788 | 788 |
get_app(pub).get(sign_uri('/api/forms/test/list?filter=all&offset=plop', user=local_user), status=400) |
789 | 789 |
get_app(pub).get(sign_uri('/api/forms/test/list?filter=all&limit=plop', user=local_user), status=400) |
790 | 790 | |
791 |
if pub.is_using_postgresql(): |
|
792 |
# just check ordering |
|
793 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=f0', user=local_user)) |
|
794 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(0, 30)] |
|
791 |
# just check ordering |
|
792 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=f0', user=local_user)) |
|
793 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(0, 30)] |
|
795 | 794 | |
796 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=-f0', user=local_user))
|
|
797 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(29, -1, -1)]
|
|
795 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=-f0', user=local_user)) |
|
796 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(29, -1, -1)] |
|
798 | 797 | |
799 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=foobar', user=local_user))
|
|
800 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(0, 30)]
|
|
798 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=foobar', user=local_user)) |
|
799 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(0, 30)] |
|
801 | 800 | |
802 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=-foobar', user=local_user))
|
|
803 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(29, -1, -1)]
|
|
801 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&order_by=-foobar', user=local_user)) |
|
802 |
assert [d['fields']['foobar'] for d in resp.json] == ['FOO BAR %02d' % i for i in range(29, -1, -1)] |
|
804 | 803 | |
805 |
# check fts
|
|
806 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&q=foo', user=local_user))
|
|
807 |
assert len(resp.json) == 30
|
|
808 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&q=baz', user=local_user))
|
|
809 |
assert len(resp.json) == 14
|
|
804 |
# check fts |
|
805 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&q=foo', user=local_user)) |
|
806 |
assert len(resp.json) == 30 |
|
807 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?full=on&q=baz', user=local_user)) |
|
808 |
assert len(resp.json) == 14 |
|
810 | 809 | |
811 | 810 | |
812 | 811 |
def test_api_list_formdata_order_by_rank(pub, local_user): |
813 |
if not pub.is_using_postgresql(): |
|
814 |
pytest.skip('this requires SQL') |
|
815 | 812 |
pub.role_class.wipe() |
816 | 813 |
role = pub.role_class(name='test') |
817 | 814 |
role.store() |
... | ... | |
938 | 935 |
params = [ |
939 | 936 |
('eq', 'FOO 2', 1), |
940 | 937 |
('ne', 'FOO 2', 3), |
941 |
('lt', 'FOO 2', 2 if pub.is_using_postgresql() else 3),
|
|
942 |
('lte', 'FOO 2', 3 if pub.is_using_postgresql() else 4),
|
|
938 |
('lt', 'FOO 2', 2), |
|
939 |
('lte', 'FOO 2', 3), |
|
943 | 940 |
('gt', 'FOO 2', 0), |
944 | 941 |
('gt', '42', 0), |
945 | 942 |
('gte', 'FOO 2', 1), |
... | ... | |
957 | 954 |
('eq', '10', 1), |
958 | 955 |
('eq', '010', 1), |
959 | 956 |
('ne', '10', 3), |
960 |
('lt', '10', 1 if pub.is_using_postgresql() else 2),
|
|
961 |
('lte', '10', 2 if pub.is_using_postgresql() else 3),
|
|
957 |
('lt', '10', 1), |
|
958 |
('lte', '10', 2), |
|
962 | 959 |
('gt', '10', 1), |
963 | 960 |
('gt', '9', 2), |
964 | 961 |
('gte', '10', 2), |
... | ... | |
1021 | 1018 |
('eq', '10', 1), |
1022 | 1019 |
('eq', '010', 1), |
1023 | 1020 |
('ne', '10', 3), |
1024 |
('lt', '10', 1 if pub.is_using_postgresql() else 2),
|
|
1025 |
('lte', '10', 2 if pub.is_using_postgresql() else 3),
|
|
1021 |
('lt', '10', 1), |
|
1022 |
('lte', '10', 2), |
|
1026 | 1023 |
('gt', '10', 1), |
1027 | 1024 |
('gt', '9', 2), |
1028 | 1025 |
('gte', '10', 2), |
... | ... | |
1041 | 1038 |
params = [ |
1042 | 1039 |
('eq', 'foo', 1), |
1043 | 1040 |
('ne', 'foo', 3), |
1044 |
('lt', 'foo', 2 if pub.is_using_postgresql() else 3),
|
|
1045 |
('lte', 'foo', 3 if pub.is_using_postgresql() else 4),
|
|
1041 |
('lt', 'foo', 2), |
|
1042 |
('lte', 'foo', 3), |
|
1046 | 1043 |
('gt', 'foo', 0), |
1047 | 1044 |
('gt', '42', 0), |
1048 | 1045 |
('gte', 'foo', 1), |
... | ... | |
1182 | 1179 |
formdata.store() |
1183 | 1180 | |
1184 | 1181 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?filter-bool=false', user=local_user)) |
1185 |
assert len(resp.json) == 2 if pub.is_using_postgresql() else 3
|
|
1182 |
assert len(resp.json) == 2 |
|
1186 | 1183 |
resp = get_app(pub).get(sign_uri('/api/forms/test/list?filter-bool=true', user=local_user)) |
1187 | 1184 |
assert len(resp.json) == 1 |
1188 | 1185 |
params = [ |
... | ... | |
1209 | 1206 | |
1210 | 1207 | |
1211 | 1208 |
def test_api_list_formdata_date_filter(pub, local_user): |
1212 |
if not pub.is_using_postgresql(): |
|
1213 |
pytest.skip('this requires SQL') |
|
1214 | ||
1215 | 1209 |
pub.role_class.wipe() |
1216 | 1210 |
role = pub.role_class(name='test') |
1217 | 1211 |
role.store() |
... | ... | |
1412 | 1406 | |
1413 | 1407 | |
1414 | 1408 |
def test_api_list_formdata_block_field_filter(pub, local_user): |
1415 |
if not pub.is_using_postgresql(): |
|
1416 |
pytest.skip('this requires SQL') |
|
1417 | ||
1418 | 1409 |
NamedDataSource.wipe() |
1419 | 1410 |
data_source = NamedDataSource(name='foobar') |
1420 | 1411 |
data_source.data_source = { |
... | ... | |
2142 | 2133 |
formdata.jump_status('finished') |
2143 | 2134 |
formdata.store() |
2144 | 2135 | |
2145 |
if not pub.is_using_postgresql(): |
|
2146 |
resp = get_app(pub).get(sign_uri('/api/forms/geojson', user=local_user), status=404) |
|
2147 |
pytest.skip('this requires SQL') |
|
2148 |
return |
|
2149 | ||
2150 | 2136 |
# check empty content if user doesn't have the appropriate role |
2151 | 2137 |
resp = get_app(pub).get(sign_uri('/api/forms/geojson', user=local_user)) |
2152 | 2138 |
assert 'features' in resp.json |
... | ... | |
2170 | 2156 |
@pytest.mark.parametrize('user', ['query-email', 'api-access']) |
2171 | 2157 |
@pytest.mark.parametrize('auth', ['signature', 'http-basic']) |
2172 | 2158 |
def test_api_global_listing(pub, local_user, user, auth): |
2173 |
if not pub.is_using_postgresql(): |
|
2174 |
resp = get_app(pub).get(sign_uri('/api/forms/geojson', user=local_user), status=404) |
|
2175 |
pytest.skip('this requires SQL') |
|
2176 |
return |
|
2177 | ||
2178 | 2159 |
pub.role_class.wipe() |
2179 | 2160 |
role = pub.role_class(name='test') |
2180 | 2161 |
role.store() |
... | ... | |
2279 | 2260 | |
2280 | 2261 | |
2281 | 2262 |
def test_api_global_listing_categories_filter(pub, local_user): |
2282 |
if not pub.is_using_postgresql(): |
|
2283 |
pytest.skip('this requires SQL') |
|
2284 |
return |
|
2285 | ||
2286 | 2263 |
Category.wipe() |
2287 | 2264 |
category1 = Category() |
2288 | 2265 |
category1.name = 'Category 1' |
... | ... | |
2391 | 2368 | |
2392 | 2369 | |
2393 | 2370 |
def test_api_include_anonymised(pub, local_user): |
2394 |
if not pub.is_using_postgresql(): |
|
2395 |
resp = get_app(pub).get(sign_uri('/api/forms/geojson', user=local_user), status=404) |
|
2396 |
pytest.skip('this requires SQL') |
|
2397 |
return |
|
2398 | ||
2399 | 2371 |
pub.role_class.wipe() |
2400 | 2372 |
role = pub.role_class(name='test') |
2401 | 2373 |
role.store() |
... | ... | |
2438 | 2410 | |
2439 | 2411 | |
2440 | 2412 |
def test_global_forms_api_user_uuid_filter(pub, local_user): |
2441 |
if not pub.is_using_postgresql(): |
|
2442 |
pytest.skip('this requires SQL') |
|
2443 |
return |
|
2444 | ||
2445 | 2413 |
pub.role_class.wipe() |
2446 | 2414 |
role = pub.role_class(name='test') |
2447 | 2415 |
role.store() |
tests/api/test_formdef.py | ||
---|---|---|
177 | 177 |
formdata.store() |
178 | 178 | |
179 | 179 |
resp = get_app(pub).get(sign_uri('/api/formdefs/?include-count=on')) |
180 |
if not pub.is_using_postgresql(): |
|
181 |
assert resp.json['data'][0]['count'] == 8 |
|
182 |
else: |
|
183 |
# 3*4 + 2*2 + 1*1 |
|
184 |
assert resp.json['data'][0]['count'] == 17 |
|
180 |
# 3*4 + 2*2 + 1*1 |
|
181 |
assert resp.json['data'][0]['count'] == 17 |
|
185 | 182 | |
186 | 183 | |
187 | 184 |
def test_formdef_list_categories_filter(pub): |
tests/api/test_user.py | ||
---|---|---|
410 | 410 | |
411 | 411 | |
412 | 412 |
def test_user_forms_limit_offset(pub, local_user): |
413 |
if not pub.is_using_postgresql(): |
|
414 |
pytest.skip('this requires SQL') |
|
415 |
return |
|
416 | ||
417 | 413 |
FormDef.wipe() |
418 | 414 |
formdef = FormDef() |
419 | 415 |
formdef.name = 'test limit offset' |
... | ... | |
614 | 610 | |
615 | 611 | |
616 | 612 |
def test_user_forms_include_accessible(pub, local_user, access): |
617 |
if not pub.is_using_postgresql(): |
|
618 |
pytest.skip('this requires SQL') |
|
619 |
return |
|
620 | ||
621 | 613 |
pub.role_class.wipe() |
622 | 614 |
role = pub.role_class(name='Foo bar') |
623 | 615 |
role.store() |
tests/backoffice_pages/test_all.py | ||
---|---|---|
269 | 269 |
assert '9 open on 50' in resp.text |
270 | 270 | |
271 | 271 |
# anonymise some formdata, they should no longer be included |
272 |
if pub.is_using_postgresql(): |
|
273 |
formdef = FormDef.get_by_urlname('form-title') |
|
274 |
for i, formdata in enumerate( |
|
275 |
formdef.data_class().select([st.Equal('status', 'wf-finished')], order_by='id') |
|
276 |
): |
|
277 |
if i >= 20: |
|
278 |
break |
|
279 |
formdata.anonymise() |
|
272 |
formdef = FormDef.get_by_urlname('form-title') |
|
273 |
for i, formdata in enumerate( |
|
274 |
formdef.data_class().select([st.Equal('status', 'wf-finished')], order_by='id') |
|
275 |
): |
|
276 |
if i >= 20: |
|
277 |
break |
|
278 |
formdata.anonymise() |
|
280 | 279 | |
281 |
for i, formdata in enumerate( |
|
282 |
formdef.data_class().select([st.Equal('status', 'wf-new')], order_by='id') |
|
283 |
): |
|
284 |
if i >= 5: |
|
285 |
break |
|
286 |
formdata.anonymise() |
|
280 |
for i, formdata in enumerate(formdef.data_class().select([st.Equal('status', 'wf-new')], order_by='id')): |
|
281 |
if i >= 5: |
|
282 |
break |
|
283 |
formdata.anonymise() |
|
287 | 284 | |
288 |
resp = app.get('/backoffice/management/forms')
|
|
289 |
assert 'Forms in your care' in resp.text
|
|
290 |
assert '4 open on 25' in resp.text
|
|
285 |
resp = app.get('/backoffice/management/forms') |
|
286 |
assert 'Forms in your care' in resp.text |
|
287 |
assert '4 open on 25' in resp.text |
|
291 | 288 | |
292 | 289 | |
293 | 290 |
def test_backoffice_management_css_class(pub): |
... | ... | |
340 | 337 |
resp = app.get('/backoffice/management/form-title/') |
341 | 338 |
resp.forms['listing-settings']['filter'] = 'all' |
342 | 339 |
resp = resp.forms['listing-settings'].submit() |
343 |
if pub.is_using_postgresql(): |
|
344 |
assert resp.text.count('data-link') == 20 |
|
345 |
else: |
|
346 |
# not using sql -> no pagination |
|
347 |
assert resp.text.count('data-link') == 50 |
|
340 |
assert resp.text.count('data-link') == 20 |
|
348 | 341 | |
349 | 342 |
# check status filter <select> |
350 | 343 |
resp = app.get('/backoffice/management/form-title/') |
351 | 344 |
resp.forms['listing-settings']['filter'] = 'done' |
352 | 345 |
resp = resp.forms['listing-settings'].submit() |
353 |
if pub.is_using_postgresql(): |
|
354 |
assert resp.text.count('data-link') == 20 |
|
355 |
resp = resp.click('Next Page') |
|
356 |
assert resp.text.count('data-link') == 13 |
|
357 |
else: |
|
358 |
assert resp.text.count('data-link') == 33 |
|
346 |
assert resp.text.count('data-link') == 20 |
|
347 |
resp = resp.click('Next Page') |
|
348 |
assert resp.text.count('data-link') == 13 |
|
359 | 349 | |
360 | 350 |
# add an extra status to workflow and move a few formdatas to it, they |
361 | 351 |
# should then be marked as open but not waiting for actions. |
... | ... | |
424 | 414 | |
425 | 415 | |
426 | 416 |
def test_backoffice_listing_pagination(pub): |
427 |
if not pub.is_using_postgresql(): |
|
428 |
pytest.skip('this requires SQL') |
|
429 |
return |
|
430 | 417 |
create_superuser(pub) |
431 | 418 |
create_environment(pub) |
432 | 419 |
app = login(get_app(pub)) |
... | ... | |
469 | 456 | |
470 | 457 | |
471 | 458 |
def test_backoffice_listing_anonymised(pub): |
472 |
if not pub.is_using_postgresql(): |
|
473 |
pytest.skip('this requires SQL') |
|
474 |
return |
|
475 | 459 |
create_superuser(pub) |
476 | 460 |
create_environment(pub) |
477 | 461 |
app = login(get_app(pub)) |
... | ... | |
488 | 472 | |
489 | 473 | |
490 | 474 |
def test_backoffice_listing_fts(pub): |
491 |
if not pub.is_using_postgresql(): |
|
492 |
pytest.skip('this requires SQL') |
|
493 |
return |
|
494 | 475 |
create_superuser(pub) |
495 | 476 |
create_environment(pub) |
496 | 477 |
formdef = FormDef.get_by_urlname('form-title') |
... | ... | |
1366 | 1347 |
@pytest.mark.parametrize('notify_on_errors', [True, False]) |
1367 | 1348 |
@pytest.mark.parametrize('record_on_errors', [True, False]) |
1368 | 1349 |
def test_backoffice_wscall_on_error(http_requests, pub, emails, notify_on_errors, record_on_errors): |
1369 |
if not pub.is_using_postgresql(): |
|
1370 |
pytest.skip('this requires SQL') |
|
1371 |
return |
|
1372 | ||
1373 | 1350 |
pub.cfg['debug'] = {'error_email': 'errors@localhost.invalid'} |
1374 | 1351 |
pub.cfg['emails'] = {'from': 'from@localhost.invalid'} |
1375 | 1352 |
pub.write_cfg() |
... | ... | |
1986 | 1963 | |
1987 | 1964 | |
1988 | 1965 |
def test_global_listing(pub): |
1989 |
if not pub.is_using_postgresql(): |
|
1990 |
pytest.skip('this requires SQL') |
|
1991 |
return |
|
1992 | ||
1993 | 1966 |
create_user(pub) |
1994 | 1967 |
create_environment(pub) |
1995 | 1968 |
app = login(get_app(pub)) |
... | ... | |
2105 | 2078 | |
2106 | 2079 | |
2107 | 2080 |
def test_global_listing_parameters_from_query_string(pub): |
2108 |
if not pub.is_using_postgresql(): |
|
2109 |
pytest.skip('this requires SQL') |
|
2110 |
return |
|
2111 | ||
2112 | 2081 |
create_user(pub) |
2113 | 2082 |
create_environment(pub) |
2114 | 2083 |
app = login(get_app(pub)) |
... | ... | |
2131 | 2100 | |
2132 | 2101 | |
2133 | 2102 |
def test_global_listing_user_label(pub): |
2134 |
if not pub.is_using_postgresql(): |
|
2135 |
pytest.skip('this requires SQL') |
|
2136 |
return |
|
2137 | ||
2138 | 2103 |
create_user(pub) |
2139 | 2104 |
FormDef.wipe() |
2140 | 2105 | |
... | ... | |
2170 | 2135 | |
2171 | 2136 | |
2172 | 2137 |
def test_management_views_with_no_formdefs(pub): |
2173 |
if not pub.is_using_postgresql(): |
|
2174 |
pytest.skip('this requires SQL') |
|
2175 |
return |
|
2176 | ||
2177 | 2138 |
create_user(pub) |
2178 | 2139 |
create_environment(pub) |
2179 | 2140 |
FormDef.wipe() |
... | ... | |
2193 | 2154 | |
2194 | 2155 | |
2195 | 2156 |
def test_category_in_global_listing(pub): |
2196 |
if not pub.is_using_postgresql(): |
|
2197 |
pytest.skip('this requires SQL') |
|
2198 |
return |
|
2199 | ||
2200 | 2157 |
FormDef.wipe() |
2201 | 2158 |
Category.wipe() |
2202 | 2159 | |
... | ... | |
2283 | 2240 | |
2284 | 2241 | |
2285 | 2242 |
def test_datetime_in_global_listing(pub): |
2286 |
if not pub.is_using_postgresql(): |
|
2287 |
pytest.skip('this requires SQL') |
|
2288 |
return |
|
2289 | ||
2290 | 2243 |
create_user(pub) |
2291 | 2244 |
create_environment(pub) |
2292 | 2245 | |
... | ... | |
2324 | 2277 | |
2325 | 2278 | |
2326 | 2279 |
def test_global_listing_anonymised(pub): |
2327 |
if not pub.is_using_postgresql(): |
|
2328 |
pytest.skip('this requires SQL') |
|
2329 |
return |
|
2330 | ||
2331 | 2280 |
create_user(pub) |
2332 | 2281 |
create_environment(pub) |
2333 | 2282 |
app = login(get_app(pub)) |
... | ... | |
2346 | 2295 | |
2347 | 2296 | |
2348 | 2297 |
def test_global_listing_geojson(pub): |
2349 |
if not pub.is_using_postgresql(): |
|
2350 |
pytest.skip('this requires SQL') |
|
2351 |
return |
|
2352 | ||
2353 | 2298 |
create_user(pub) |
2354 | 2299 |
create_environment(pub) |
2355 | 2300 | |
... | ... | |
2381 | 2326 | |
2382 | 2327 | |
2383 | 2328 |
def test_global_map(pub): |
2384 |
if not pub.is_using_postgresql(): |
|
2385 |
pytest.skip('this requires SQL') |
|
2386 |
return |
|
2387 | ||
2388 | 2329 |
create_user(pub) |
2389 | 2330 |
create_environment(pub) |
2390 | 2331 | |
... | ... | |
2447 | 2388 |
resp = resp.form.submit() |
2448 | 2389 |
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id |
2449 | 2390 | |
2450 |
if pub.is_using_postgresql(): |
|
2451 |
# check looking up on a custom display_id |
|
2452 |
formdata.id_display = '999999' |
|
2453 |
formdata.store() |
|
2454 |
assert formdata.get_display_id() == '999999' |
|
2455 |
resp = app.get('/backoffice/management/').follow() |
|
2456 |
resp.form['query'] = formdata.get_display_id() |
|
2457 |
resp = resp.form.submit() |
|
2458 |
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id |
|
2459 | ||
2460 |
# try it from the global listing |
|
2461 |
resp = app.get('/backoffice/management/listing') |
|
2462 |
assert 'id="lookup-box"' in resp.text |
|
2463 |
resp.forms[0]['query'] = formdata.tracking_code |
|
2464 |
resp = resp.forms[0].submit() |
|
2465 |
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id |
|
2466 |
resp = resp.follow() |
|
2467 |
assert 'The form has been recorded' in resp.text |
|
2391 |
# check looking up on a custom display_id |
|
2392 |
formdata.id_display = '999999' |
|
2393 |
formdata.store() |
|
2394 |
assert formdata.get_display_id() == '999999' |
|
2395 |
resp = app.get('/backoffice/management/').follow() |
|
2396 |
resp.form['query'] = formdata.get_display_id() |
|
2397 |
resp = resp.form.submit() |
|
2398 |
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id |
|
2468 | 2399 | |
2469 |
resp = app.get('/backoffice/management/listing') |
|
2470 |
resp.forms[0]['query'] = 'AAAAAAAA' |
|
2471 |
resp = resp.forms[0].submit() |
|
2472 |
assert resp.location == 'http://example.net/backoffice/management/listing' |
|
2473 |
resp = resp.follow() |
|
2474 |
assert 'No such tracking code or identifier.' in resp.text |
|
2400 |
# try it from the global listing |
|
2401 |
resp = app.get('/backoffice/management/listing') |
|
2402 |
assert 'id="lookup-box"' in resp.text |
|
2403 |
resp.forms[0]['query'] = formdata.tracking_code |
|
2404 |
resp = resp.forms[0].submit() |
|
2405 |
assert resp.location == 'http://example.net/backoffice/management/form-title/%s/' % formdata.id |
|
2406 |
resp = resp.follow() |
|
2407 |
assert 'The form has been recorded' in resp.text |
|
2408 | ||
2409 |
resp = app.get('/backoffice/management/listing') |
|
2410 |
resp.forms[0]['query'] = 'AAAAAAAA' |
|
2411 |
resp = resp.forms[0].submit() |
|
2412 |
assert resp.location == 'http://example.net/backoffice/management/listing' |
|
2413 |
resp = resp.follow() |
|
2414 |
assert 'No such tracking code or identifier.' in resp.text |
|
2475 | 2415 | |
2476 | 2416 | |
2477 | 2417 |
def test_backoffice_sidebar_user_context(pub): |
2478 |
if not pub.is_using_postgresql(): |
|
2479 |
pytest.skip('this requires SQL') |
|
2480 |
return |
|
2481 | ||
2482 | 2418 |
user = create_user(pub) |
2483 | 2419 |
create_environment(pub) |
2484 | 2420 |
form_class = FormDef.get_by_urlname('form-title').data_class() |
... | ... | |
2576 | 2512 | |
2577 | 2513 | |
2578 | 2514 |
def test_count_open(pub): |
2579 |
if not pub.is_using_postgresql(): |
|
2580 |
pytest.skip('this requires SQL') |
|
2581 |
return |
|
2582 | 2515 |
create_user(pub) |
2583 | 2516 | |
2584 | 2517 |
FormDef.wipe() |
... | ... | |
2710 | 2643 | |
2711 | 2644 | |
2712 | 2645 |
def test_backoffice_backoffice_submission_in_global_listing(pub): |
2713 |
if not pub.is_using_postgresql(): |
|
2714 |
pytest.skip('this requires SQL') |
|
2715 |
return |
|
2716 | 2646 |
create_superuser(pub) |
2717 | 2647 |
create_environment(pub) |
2718 | 2648 | |
... | ... | |
2758 | 2688 |
resp = app.get('/backoffice/management/form-title/') |
2759 | 2689 |
assert 'advisory-lock' not in resp.text |
2760 | 2690 | |
2761 |
if pub.is_using_postgresql(): |
|
2762 |
# check global view |
|
2763 |
resp = app2.get('/backoffice/management/listing?limit=100') |
|
2764 |
assert 'advisory-lock' in resp.text |
|
2765 |
resp = app.get('/backoffice/management/listing?limit=100') |
|
2766 |
assert 'advisory-lock' not in resp.text |
|
2691 |
# check global view |
|
2692 |
resp = app2.get('/backoffice/management/listing?limit=100') |
|
2693 |
assert 'advisory-lock' in resp.text |
|
2694 |
resp = app.get('/backoffice/management/listing?limit=100') |
|
2695 |
assert 'advisory-lock' not in resp.text |
|
2767 | 2696 | |
2768 | 2697 |
resp = app.get('/backoffice/management/form-title/' + first_link) |
2769 | 2698 |
assert 'Be warned forms of this user are also being looked' not in resp.text |
... | ... | |
2810 | 2739 | |
2811 | 2740 | |
2812 | 2741 |
def test_backoffice_advisory_lock_related_formdatas(pub): |
2813 |
if not pub.is_using_postgresql(): |
|
2814 |
pytest.skip('this requires SQL') |
|
2815 |
return |
|
2816 | 2742 |
pub.session_manager.session_class.wipe() |
2817 | 2743 |
user = create_superuser(pub) |
2818 | 2744 |
create_environment(pub) |
... | ... | |
3622 | 3548 | |
3623 | 3549 | |
3624 | 3550 |
def test_backoffice_logged_errors(pub): |
3625 |
if not pub.is_using_postgresql(): |
|
3626 |
pytest.skip('this requires SQL') |
|
3627 |
return |
|
3628 | ||
3629 | 3551 |
Workflow.wipe() |
3630 | 3552 |
workflow = Workflow.get_default_workflow() |
3631 | 3553 |
workflow.id = '12' |
... | ... | |
4144 | 4066 |
assert target_data_class.count() == 0 |
4145 | 4067 |
# resubmit it through backoffice submission |
4146 | 4068 |
resp = resp.form.submit(name='button_resubmit') |
4147 |
if pub.is_using_postgresql(): |
|
4148 |
assert pub.loggederror_class.count() == 0 |
|
4069 |
assert pub.loggederror_class.count() == 0 |
|
4149 | 4070 |
assert target_data_class.count() == 1 |
4150 | 4071 |
target_formdata = target_data_class.select()[0] |
4151 | 4072 | |
... | ... | |
4264 | 4185 |
assert target_data_class.count() == 0 |
4265 | 4186 |
# resubmit it through backoffice submission |
4266 | 4187 |
resp = resp.form.submit(name='button_resubmit') |
4267 |
if pub.is_using_postgresql(): |
|
4268 |
assert pub.loggederror_class.count() == 0 |
|
4188 |
assert pub.loggederror_class.count() == 0 |
|
4269 | 4189 |
assert target_data_class.count() == 1 |
4270 | 4190 |
target_formdata = target_data_class.select()[0] |
4271 | 4191 |
tests/backoffice_pages/test_carddata.py | ||
---|---|---|
552 | 552 | |
553 | 553 | |
554 | 554 |
def test_backoffice_cards_wscall_failure_display(http_requests, pub): |
555 |
if not pub.is_using_postgresql(): |
|
556 |
pytest.skip('this requires SQL') |
|
557 |
return |
|
558 | ||
559 | 555 |
user = create_user(pub) |
560 | 556 | |
561 | 557 |
Workflow.wipe() |
tests/backoffice_pages/test_columns.py | ||
---|---|---|
309 | 309 |
resp = app.get('/backoffice/management/form-title/') |
310 | 310 |
assert resp.text.count('</th>') == 6 # four columns |
311 | 311 | |
312 |
if not pub.is_using_postgresql(): |
|
313 |
# no support for relation columns unless using SQL |
|
314 |
assert 'user-label$3' not in resp.forms['listing-settings'].fields |
|
315 |
return |
|
316 | 312 |
resp.forms['listing-settings']['user-label$3'].checked = True |
317 | 313 |
resp = resp.forms['listing-settings'].submit() |
318 | 314 |
assert resp.text.count('</th>') == 7 |
... | ... | |
381 | 377 |
app = login(get_app(pub)) |
382 | 378 |
resp = app.get('/backoffice/management/form-title/') |
383 | 379 |
assert resp.text.count('</th>') == 6 # four columns |
384 |
if not pub.is_using_postgresql(): |
|
385 |
# no support for relation columns unless using SQL |
|
386 |
assert '4$1' not in resp.forms['listing-settings'].fields |
|
387 |
return |
|
388 | 380 |
assert '4$0' not in resp.forms['listing-settings'].fields |
389 | 381 |
resp.forms['listing-settings']['4$1'].checked = True |
390 | 382 |
resp.forms['listing-settings']['4$2'].checked = True |
... | ... | |
415 | 407 | |
416 | 408 | |
417 | 409 |
def test_backoffice_block_columns(pub): |
418 |
if not pub.is_using_postgresql(): |
|
419 |
pytest.skip('this requires SQL') |
|
420 |
return |
|
421 | ||
422 | 410 |
pub.user_class.wipe() |
423 | 411 |
create_superuser(pub) |
424 | 412 |
pub.role_class.wipe() |
... | ... | |
520 | 508 | |
521 | 509 | |
522 | 510 |
def test_backoffice_block_email_column(pub): |
523 |
if not pub.is_using_postgresql(): |
|
524 |
pytest.skip('this requires SQL') |
|
525 |
return |
|
526 | ||
527 | 511 |
pub.user_class.wipe() |
528 | 512 |
create_superuser(pub) |
529 | 513 |
pub.role_class.wipe() |
... | ... | |
585 | 569 | |
586 | 570 | |
587 | 571 |
def test_backoffice_block_bool_column(pub): |
588 |
if not pub.is_using_postgresql(): |
|
589 |
pytest.skip('this requires SQL') |
|
590 |
return |
|
591 | ||
592 | 572 |
pub.user_class.wipe() |
593 | 573 |
create_superuser(pub) |
594 | 574 |
pub.role_class.wipe() |
... | ... | |
649 | 629 | |
650 | 630 | |
651 | 631 |
def test_backoffice_block_date_column(pub): |
652 |
if not pub.is_using_postgresql(): |
|
653 |
pytest.skip('this requires SQL') |
|
654 |
return |
|
655 | ||
656 | 632 |
pub.user_class.wipe() |
657 | 633 |
create_superuser(pub) |
658 | 634 |
pub.role_class.wipe() |
... | ... | |
713 | 689 | |
714 | 690 | |
715 | 691 |
def test_backoffice_block_file_column(pub): |
716 |
if not pub.is_using_postgresql(): |
|
717 |
pytest.skip('this requires SQL') |
|
718 |
return |
|
719 | ||
720 | 692 |
pub.user_class.wipe() |
721 | 693 |
create_superuser(pub) |
722 | 694 |
pub.role_class.wipe() |
... | ... | |
780 | 752 | |
781 | 753 | |
782 | 754 |
def test_backoffice_block_column_position(pub): |
783 |
if not pub.is_using_postgresql(): |
|
784 |
pytest.skip('this requires SQL') |
|
785 |
return |
|
786 | ||
787 | 755 |
pub.user_class.wipe() |
788 | 756 |
create_superuser(pub) |
789 | 757 |
pub.role_class.wipe() |
tests/backoffice_pages/test_custom_view.py | ||
---|---|---|
827 | 827 | |
828 | 828 | |
829 | 829 |
def test_backoffice_custom_view_sort_field(pub): |
830 |
if not pub.is_using_postgresql(): |
|
831 |
pytest.skip('this requires SQL') |
|
832 |
return |
|
833 | ||
834 | 830 |
create_superuser(pub) |
835 | 831 | |
836 | 832 |
FormDef.wipe() |
tests/backoffice_pages/test_export.py | ||
---|---|---|
589 | 589 | |
590 | 590 | |
591 | 591 |
def test_backoffice_csv_export_ordering(pub): |
592 |
if not pub.is_using_postgresql(): |
|
593 |
pytest.skip('this requires SQL') |
|
594 |
return |
|
595 | ||
596 | 592 |
create_superuser(pub) |
597 | 593 | |
598 | 594 |
FormDef.wipe() |
tests/backoffice_pages/test_filters.py | ||
---|---|---|
349 | 349 |
assert resp.text.count('<td>b</td>') == 0 |
350 | 350 |
assert resp.text.count('<td>d</td>') > 0 |
351 | 351 | |
352 |
if not pub.is_using_postgresql():
|
|
353 |
# in pickle all options are always displayed
|
|
352 |
# in postgresql, option 'c' is never used so not even listed
|
|
353 |
with pytest.raises(ValueError):
|
|
354 | 354 |
resp.forms['listing-settings']['filter-4-value'].value = 'c' |
355 |
resp.forms['listing-settings']['filter-4-operator'].value = 'eq' |
|
356 |
resp = resp.forms['listing-settings'].submit() |
|
357 |
assert resp.text.count('<td>â</td>') == 0 |
|
358 |
assert resp.text.count('<td>b</td>') == 0 |
|
359 |
assert resp.text.count('<td>c</td>') == 0 |
|
360 | 355 | |
361 |
else: |
|
362 |
# in postgresql, option 'c' is never used so not even listed |
|
363 |
with pytest.raises(ValueError): |
|
364 |
resp.forms['listing-settings']['filter-4-value'].value = 'c' |
|
356 |
# check json view used to fill select filters from javascript |
|
357 |
resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=4&' + resp.request.query_string) |
|
358 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
359 |
resp2 = app.get( |
|
360 |
resp.request.path + 'filter-options?filter_field_id=4&_search=d&' + resp.request.query_string |
|
361 |
) |
|
362 |
assert [x['id'] for x in resp2.json['data']] == ['d'] |
|
363 |
resp2 = app.get( |
|
364 |
resp.request.path + 'filter-options?filter_field_id=7&' + resp.request.query_string, status=404 |
|
365 |
) |
|
365 | 366 | |
366 |
# check json view used to fill select filters from javascript |
|
367 |
for status in ('all', 'waiting', 'pending', 'done', 'accepted'): |
|
368 |
resp.forms['listing-settings']['filter'] = status |
|
369 |
resp = resp.forms['listing-settings'].submit() |
|
367 | 370 |
resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=4&' + resp.request.query_string) |
368 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
369 |
resp2 = app.get( |
|
370 |
resp.request.path + 'filter-options?filter_field_id=4&_search=d&' + resp.request.query_string |
|
371 |
) |
|
372 |
assert [x['id'] for x in resp2.json['data']] == ['d'] |
|
373 |
resp2 = app.get( |
|
374 |
resp.request.path + 'filter-options?filter_field_id=7&' + resp.request.query_string, status=404 |
|
375 |
) |
|
376 | ||
377 |
for status in ('all', 'waiting', 'pending', 'done', 'accepted'): |
|
378 |
resp.forms['listing-settings']['filter'] = status |
|
379 |
resp = resp.forms['listing-settings'].submit() |
|
380 |
resp2 = app.get( |
|
381 |
resp.request.path + 'filter-options?filter_field_id=4&' + resp.request.query_string |
|
382 |
) |
|
383 |
if status == 'accepted': |
|
384 |
assert [x['id'] for x in resp2.json['data']] == [] |
|
385 |
else: |
|
386 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
371 |
if status == 'accepted': |
|
372 |
assert [x['id'] for x in resp2.json['data']] == [] |
|
373 |
else: |
|
374 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
387 | 375 | |
388 | 376 | |
389 | 377 |
def test_backoffice_item_double_filter(pub): |
390 |
if not pub.is_using_postgresql(): |
|
391 |
pytest.skip('this requires SQL') |
|
392 |
return |
|
393 | 378 |
pub.user_class.wipe() |
394 | 379 |
create_superuser(pub) |
395 | 380 |
pub.role_class.wipe() |
... | ... | |
566 | 551 |
assert resp.text.count('<td>b</td>') == 0 |
567 | 552 |
assert resp.text.count('<td>d</td>') > 0 |
568 | 553 | |
569 |
if not pub.is_using_postgresql():
|
|
570 |
# in pickle all options are always displayed
|
|
554 |
# in postgresql, option 'c' is never used so not even listed
|
|
555 |
with pytest.raises(ValueError):
|
|
571 | 556 |
resp.forms['listing-settings']['filter-bo0-1-value'].value = 'c' |
572 |
resp.forms['listing-settings']['filter-bo0-1-operator'].value = 'eq' |
|
573 |
resp = resp.forms['listing-settings'].submit() |
|
574 |
assert resp.text.count('<td>â</td>') == 0 |
|
575 |
assert resp.text.count('<td>b</td>') == 0 |
|
576 |
assert resp.text.count('<td>c</td>') == 0 |
|
577 | 557 | |
578 |
else: |
|
579 |
# in postgresql, option 'c' is never used so not even listed |
|
580 |
with pytest.raises(ValueError): |
|
581 |
resp.forms['listing-settings']['filter-bo0-1-value'].value = 'c' |
|
558 |
# check json view used to fill select filters from javascript |
|
559 |
resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=bo0-1&' + resp.request.query_string) |
|
560 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
561 |
resp2 = app.get( |
|
562 |
resp.request.path + 'filter-options?filter_field_id=bo0-1&_search=d&' + resp.request.query_string |
|
563 |
) |
|
564 |
assert [x['id'] for x in resp2.json['data']] == ['d'] |
|
582 | 565 | |
583 |
# check json view used to fill select filters from javascript |
|
566 |
for status in ('all', 'waiting', 'pending', 'done', 'accepted'): |
|
567 |
resp.forms['listing-settings']['filter'] = status |
|
568 |
resp = resp.forms['listing-settings'].submit() |
|
584 | 569 |
resp2 = app.get( |
585 | 570 |
resp.request.path + 'filter-options?filter_field_id=bo0-1&' + resp.request.query_string |
586 | 571 |
) |
587 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
588 |
resp2 = app.get( |
|
589 |
resp.request.path + 'filter-options?filter_field_id=bo0-1&_search=d&' + resp.request.query_string |
|
590 |
) |
|
591 |
assert [x['id'] for x in resp2.json['data']] == ['d'] |
|
592 | ||
593 |
for status in ('all', 'waiting', 'pending', 'done', 'accepted'): |
|
594 |
resp.forms['listing-settings']['filter'] = status |
|
595 |
resp = resp.forms['listing-settings'].submit() |
|
596 |
resp2 = app.get( |
|
597 |
resp.request.path + 'filter-options?filter_field_id=bo0-1&' + resp.request.query_string |
|
598 |
) |
|
599 |
if status == 'accepted': |
|
600 |
assert [x['id'] for x in resp2.json['data']] == [] |
|
601 |
else: |
|
602 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
572 |
if status == 'accepted': |
|
573 |
assert [x['id'] for x in resp2.json['data']] == [] |
|
574 |
else: |
|
575 |
assert [x['id'] for x in resp2.json['data']] == ['â', 'b', 'd'] |
|
603 | 576 | |
604 | 577 | |
605 | 578 |
def test_backoffice_items_filter(pub): |
... | ... | |
681 | 654 |
assert resp.text.count('<td>â</td>') > 0 |
682 | 655 |
assert resp.text.count('<td>b, d</td>') == 0 |
683 | 656 | |
684 |
if pub.is_using_postgresql(): |
|
685 |
# option 'c' is never used so not even listed |
|
686 |
with pytest.raises(ValueError): |
|
687 |
resp.forms['listing-settings']['filter-4-value'].value = 'c' |
|
688 |
else: |
|
657 |
# option 'c' is never used so not even listed |
|
658 |
with pytest.raises(ValueError): |
|
689 | 659 |
resp.forms['listing-settings']['filter-4-value'].value = 'c' |
690 |
resp.forms['listing-settings']['filter-4-operator'].value = 'eq' |
|
691 |
resp = resp.forms['listing-settings'].submit() |
|
692 |
assert resp.text.count('<td>â, b</td>') == 0 |
|
693 |
assert resp.text.count('<td>â</td>') == 0 |
|
694 |
assert resp.text.count('<td>b, d</td>') == 0 |
|
695 |
assert resp.text.count('data-link') == 0 # no rows |
|
696 | 660 | |
697 | 661 | |
698 | 662 |
def test_backoffice_items_cards_filter(pub): |
... | ... | |
766 | 730 |
resp.forms['listing-settings']['filter-1'].checked = True |
767 | 731 |
resp = resp.forms['listing-settings'].submit() |
768 | 732 | |
769 |
if pub.is_using_postgresql(): |
|
770 |
# option 'bar' is never used so not even listed |
|
771 |
assert [x[2] for x in resp.forms['listing-settings']['filter-1-value'].options] == [ |
|
772 |
'', |
|
773 |
'card baz', |
|
774 |
'card foo', |
|
775 |
'card foo, bar', |
|
776 |
] |
|
777 |
else: |
|
778 |
assert [x[2] for x in resp.forms['listing-settings']['filter-1-value'].options] == [ |
|
779 |
'', |
|
780 |
'card bar', |
|
781 |
'card baz', |
|
782 |
'card foo', |
|
783 |
'card foo, bar', |
|
784 |
] |
|
733 |
# option 'bar' is never used so not even listed |
|
734 |
assert [x[2] for x in resp.forms['listing-settings']['filter-1-value'].options] == [ |
|
735 |
'', |
|
736 |
'card baz', |
|
737 |
'card foo', |
|
738 |
'card foo, bar', |
|
739 |
] |
|
785 | 740 | |
786 | 741 |
resp.forms['listing-settings']['filter-1-value'].value = card_ids['foo'] |
787 | 742 |
resp = resp.forms['listing-settings'].submit() |
... | ... | |
957 | 912 | |
958 | 913 | |
959 | 914 |
def test_backoffice_date_filter(pub): |
960 |
if not pub.is_using_postgresql(): |
|
961 |
pytest.skip('this requires SQL') |
|
962 |
return |
|
963 | 915 |
pub.user_class.wipe() |
964 | 916 |
create_superuser(pub) |
965 | 917 |
pub.role_class.wipe() |
... | ... | |
1363 | 1315 | |
1364 | 1316 | |
1365 | 1317 |
def test_backoffice_block_field_filter(pub): |
1366 |
if not pub.is_using_postgresql(): |
|
1367 |
pytest.skip('this requires SQL') |
|
1368 | ||
1369 | 1318 |
pub.user_class.wipe() |
1370 | 1319 |
create_superuser(pub) |
1371 | 1320 |
pub.role_class.wipe() |
tests/backoffice_pages/test_form_inspect.py | ||
---|---|---|
349 | 349 | |
350 | 350 | |
351 | 351 |
def test_inspect_page_with_related_objects(pub): |
352 |
if not pub.is_using_postgresql(): |
|
353 |
pytest.skip('this requires SQL') |
|
354 |
return |
|
355 | ||
356 | 352 |
user = create_user(pub, is_admin=True) |
357 | 353 | |
358 | 354 |
FormDef.wipe() |
... | ... | |
746 | 742 | |
747 | 743 | |
748 | 744 |
def test_inspect_page_lazy_list(pub): |
749 |
if not pub.is_using_postgresql(): |
|
750 |
pytest.skip('this requires SQL') |
|
751 |
return |
|
752 | ||
753 | 745 |
FormDef.wipe() |
754 | 746 | |
755 | 747 |
formdef = FormDef() |
tests/backoffice_pages/test_statistics.py | ||
---|---|---|
38 | 38 |
create_user(pub) |
39 | 39 |
create_environment(pub) |
40 | 40 |
FormDef.wipe() |
41 |
if pub.is_using_postgresql(): |
|
42 |
from wcs.sql import drop_global_views, get_connection_and_cursor |
|
41 |
from wcs.sql import drop_global_views, get_connection_and_cursor |
|
43 | 42 | |
44 |
conn, cur = get_connection_and_cursor()
|
|
45 |
drop_global_views(conn, cur)
|
|
46 |
conn.commit()
|
|
47 |
cur.close()
|
|
43 |
conn, cur = get_connection_and_cursor() |
|
44 |
drop_global_views(conn, cur) |
|
45 |
conn.commit() |
|
46 |
cur.close() |
|
48 | 47 | |
49 | 48 |
app = login(get_app(pub)) |
50 | 49 |
resp = app.get('/backoffice/management/statistics') |
... | ... | |
72 | 71 |
assert 'Total number of records: 17' in resp.text |
73 | 72 |
assert '<h2>Filters</h2>' in resp.text |
74 | 73 |
assert 'Status: Open' in resp.text |
75 |
if pub.is_using_postgresql(): |
|
76 |
resp.forms['listing-settings']['filter'].value = 'waiting' |
|
77 |
resp = resp.forms['listing-settings'].submit() |
|
78 |
assert 'Total number of records: 17' in resp.text |
|
79 |
assert '<h2>Filters</h2>' in resp.text |
|
80 |
assert 'Status: Waiting for an action' in resp.text |
|
81 |
else: |
|
82 |
assert 'waiting' not in [x[0] for x in resp.forms['listing-settings']['filter'].options] |
|
74 |
resp.forms['listing-settings']['filter'].value = 'waiting' |
|
75 |
resp = resp.forms['listing-settings'].submit() |
|
76 |
assert 'Total number of records: 17' in resp.text |
|
77 |
assert '<h2>Filters</h2>' in resp.text |
|
78 |
assert 'Status: Waiting for an action' in resp.text |
|
83 | 79 | |
84 | 80 |
resp.forms['listing-settings']['filter'].value = 'done' |
85 | 81 |
resp = resp.forms['listing-settings'].submit() |
tests/form_pages/test_all.py | ||
---|---|---|
1521 | 1521 |
user.store() |
1522 | 1522 |
resp = resp.form.submit('submit') |
1523 | 1523 |
resp = resp.follow() |
1524 |
if pub.is_using_postgresql(): |
|
1525 |
assert 'Sorry, your session have been lost.' in resp |
|
1526 |
else: |
|
1527 |
assert 'The form has been recorded' in resp |
|
1528 |
assert formdef.data_class().count() == 1 |
|
1529 |
assert formdef.data_class().select()[0].user_id is None |
|
1524 |
assert 'Sorry, your session have been lost.' in resp |
|
1530 | 1525 | |
1531 | 1526 | |
1532 | 1527 |
def test_form_titles(pub): |
... | ... | |
2836 | 2831 |
assert formdef.data_class().get(data_id).evolution[-1].status == 'wf-%s' % st2.id |
2837 | 2832 | |
2838 | 2833 |
# jump to a nonexistent status == do not jump, but add a LoggedError |
2839 |
if pub.is_using_postgresql(): |
|
2840 |
pub.loggederror_class.wipe() |
|
2841 |
assert pub.loggederror_class.count() == 0 |
|
2834 |
pub.loggederror_class.wipe() |
|
2835 |
assert pub.loggederror_class.count() == 0 |
|
2842 | 2836 |
editable.status = 'deleted_status_id' |
2843 | 2837 |
workflow.store() |
2844 | 2838 |
# go back to st1 |
... | ... | |
2854 | 2848 |
resp = resp.forms[0].submit('submit') |
2855 | 2849 |
resp = resp.follow() |
2856 | 2850 |
assert formdef.data_class().get(data_id).status == 'wf-%s' % st1.id # stay on st1 |
2857 |
if pub.is_using_postgresql(): |
|
2858 |
assert pub.loggederror_class.count() == 1 |
|
2859 |
logged_error = pub.loggederror_class.select()[0] |
|
2860 |
assert logged_error.formdata_id == str(formdata.id) |
|
2861 |
assert logged_error.formdef_id == formdef.id |
|
2862 |
assert logged_error.workflow_id == workflow.id |
|
2863 |
assert logged_error.status_id == st1.id |
|
2864 |
assert logged_error.status_item_id == editable.id |
|
2865 |
assert logged_error.occurences_count == 1 |
|
2851 |
assert pub.loggederror_class.count() == 1 |
|
2852 |
logged_error = pub.loggederror_class.select()[0] |
|
2853 |
assert logged_error.formdata_id == str(formdata.id) |
|
2854 |
assert logged_error.formdef_id == formdef.id |
|
2855 |
assert logged_error.workflow_id == workflow.id |
|
2856 |
assert logged_error.status_id == st1.id |
|
2857 |
assert logged_error.status_item_id == editable.id |
|
2858 |
assert logged_error.occurences_count == 1 |
|
2866 | 2859 | |
2867 | 2860 |
# do it again: increment logged_error.occurences_count |
2868 | 2861 |
page = login(get_app(pub), username='foo', password='foo').get('/test/%s/' % data_id) |
... | ... | |
2873 | 2866 |
resp = resp.forms[0].submit('submit') |
2874 | 2867 |
resp = resp.follow() |
2875 | 2868 |
assert formdef.data_class().get(data_id).status == 'wf-%s' % st1.id # stay on st1 |
2876 |
if pub.is_using_postgresql(): |
|
2877 |
assert pub.loggederror_class.count() == 1 |
|
2878 |
logged_error = pub.loggederror_class.select()[0] |
|
2879 |
assert logged_error.occurences_count == 2 |
|
2869 |
assert pub.loggederror_class.count() == 1 |
|
2870 |
logged_error = pub.loggederror_class.select()[0] |
|
2871 |
assert logged_error.occurences_count == 2 |
|
2880 | 2872 | |
2881 | 2873 | |
2882 | 2874 |
def test_form_edit_autocomplete_list(pub): |
... | ... | |
3765 | 3757 |
assert not resp.form['f0$elementbar'].checked |
3766 | 3758 |
assert not resp.form['f0$elementbaz'].checked |
3767 | 3759 | |
3768 |
if pub.is_using_postgresql(): |
|
3769 |
assert pub.loggederror_class.count() == 1 |
|
3770 |
logged_error = pub.loggederror_class.select()[0] |
|
3771 |
assert logged_error.summary == 'Invalid value for items prefill on field "items"' |
|
3772 |
pub.loggederror_class.wipe() |
|
3760 |
assert pub.loggederror_class.count() == 1 |
|
3761 |
logged_error = pub.loggederror_class.select()[0] |
|
3762 |
assert logged_error.summary == 'Invalid value for items prefill on field "items"' |
|
3763 |
pub.loggederror_class.wipe() |
|
3773 | 3764 | |
3774 | 3765 | |
3775 | 3766 |
def test_form_page_changing_prefill(pub): |
... | ... | |
5006 | 4997 |
autosave_data['_ajax_form_token'] = resp.form['_form_id'].value |
5007 | 4998 |
resp_autosave = app.post('/test/autosave', params=autosave_data) |
5008 | 4999 |
formdata.refresh_from_storage() |
5009 |
if pub.is_using_postgresql(): |
|
5010 |
assert resp_autosave.json != {'result': 'success'} |
|
5011 |
assert formdata.data['3'] == '1' |
|
5012 |
else: |
|
5013 |
# with pickle invalid data has been saved |
|
5014 |
assert resp_autosave.json == {'result': 'success'} |
|
5015 |
assert formdata.data['3'] == 'tmp' |
|
5000 |
assert resp_autosave.json != {'result': 'success'} |
|
5001 |
assert formdata.data['3'] == '1' |
|
5016 | 5002 |
# validate |
5017 | 5003 |
resp = resp.form.submit('submit') # -> submit |
5018 | 5004 | |
... | ... | |
5546 | 5532 |
resp = resp.follow() |
5547 | 5533 |
assert 'Error rendering message.' in resp.text |
5548 | 5534 | |
5549 |
if pub.is_using_postgresql(): |
|
5550 |
assert pub.loggederror_class.count() == 1 |
|
5551 |
logged_error = pub.loggederror_class.select()[0] |
|
5552 |
assert logged_error.summary == "Error in template of workflow message ('int' object is not iterable)" |
|
5535 |
assert pub.loggederror_class.count() == 1 |
|
5536 |
logged_error = pub.loggederror_class.select()[0] |
|
5537 |
assert logged_error.summary == "Error in template of workflow message ('int' object is not iterable)" |
|
5553 | 5538 | |
5554 | 5539 | |
5555 | 5540 |
def test_session_cookie_flags(pub): |
... | ... | |
6030 | 6015 |
app = login(get_app(pub), username='foo', password='foo') |
6031 | 6016 | |
6032 | 6017 |
resp = app.get('/backoffice/data/items/') |
6033 |
if pub.is_using_postgresql(): |
|
6034 |
assert resp.text.count('<tr') == 21 # thead + 20 items (max per page) |
|
6035 |
else: |
|
6036 |
assert resp.text.count('<tr') == 31 # thead + all items |
|
6018 |
assert resp.text.count('<tr') == 21 # thead + 20 items (max per page) |
|
6037 | 6019 |
resp.forms['listing-settings']['filter-0'].checked = True |
6038 | 6020 |
resp = resp.forms['listing-settings'].submit() |
6039 | 6021 | |
... | ... | |
6524 | 6506 |
resp2 = app.get(select2_url + '?q=hell') |
6525 | 6507 |
assert emails.count() == 1 |
6526 | 6508 |
assert emails.get_latest('subject') == '[ERROR] [DATASOURCE] Error loading JSON data source (...)' |
6527 |
if pub.is_using_postgresql(): |
|
6528 |
assert pub.loggederror_class.count() == 1 |
|
6529 |
logged_error = pub.loggederror_class.select()[0] |
|
6530 |
assert logged_error.workflow_id is None |
|
6531 |
assert logged_error.summary == '[DATASOURCE] Error loading JSON data source (...)' |
|
6509 |
assert pub.loggederror_class.count() == 1 |
|
6510 |
logged_error = pub.loggederror_class.select()[0] |
|
6511 |
assert logged_error.workflow_id is None |
|
6512 |
assert logged_error.summary == '[DATASOURCE] Error loading JSON data source (...)' |
|
6532 | 6513 | |
6533 | 6514 |
data_source.notify_on_errors = False |
6534 | 6515 |
data_source.store() |
... | ... | |
6891 | 6872 | |
6892 | 6873 | |
6893 | 6874 |
def test_logged_errors(pub): |
6894 |
if not pub.is_using_postgresql(): |
|
6895 |
pytest.skip('this requires SQL') |
|
6896 |
return |
|
6897 | ||
6898 | 6875 |
Workflow.wipe() |
6899 | 6876 |
workflow = Workflow.get_default_workflow() |
6900 | 6877 |
workflow.id = '12' |
... | ... | |
8896 | 8873 |
resp = resp.form.submit('submit') # -> submission |
8897 | 8874 |
resp = resp.follow() |
8898 | 8875 |
assert create_formdata['target_formdef'].data_class().count() == 0 |
8899 |
if pub.is_using_postgresql(): |
|
8900 |
assert pub.loggederror_class.count() == 0 |
|
8876 |
assert pub.loggederror_class.count() == 0 |
|
8901 | 8877 |
resp = resp.form.submit('button_resubmit') |
8902 |
if pub.is_using_postgresql(): |
|
8903 |
assert pub.loggederror_class.count() == 0 |
|
8878 |
assert pub.loggederror_class.count() == 0 |
|
8904 | 8879 | |
8905 | 8880 | |
8906 | 8881 |
def test_create_formdata_locked_prefill_parent(create_formdata): |
tests/form_pages/test_block.py | ||
---|---|---|
1808 | 1808 |
resp = get_app(pub).get(formdef.get_url(), status=500) |
1809 | 1809 |
assert 'A fatal error happened.' in resp.text |
1810 | 1810 | |
1811 |
if pub.is_using_postgresql(): |
|
1812 |
assert pub.loggederror_class.count() == 1 |
|
1813 |
logged_error = pub.loggederror_class.select()[0] |
|
1814 |
assert '(id:%s)' % logged_error.id in resp.text |
|
1815 |
resp = get_app(pub).get(formdef.get_url(), status=500) |
|
1816 |
assert '(id:%s)' % logged_error.id in resp.text |
|
1817 |
logged_error = pub.loggederror_class.select()[0] |
|
1818 |
assert logged_error.occurences_count == 2 |
|
1811 |
assert pub.loggederror_class.count() == 1 |
|
1812 |
logged_error = pub.loggederror_class.select()[0] |
|
1813 |
assert '(id:%s)' % logged_error.id in resp.text |
|
1814 |
resp = get_app(pub).get(formdef.get_url(), status=500) |
|
1815 |
assert '(id:%s)' % logged_error.id in resp.text |
|
1816 |
logged_error = pub.loggederror_class.select()[0] |
|
1817 |
assert logged_error.occurences_count == 2 |
|
1819 | 1818 | |
1820 | 1819 | |
1821 | 1820 |
def test_block_with_static_condition(pub): |
tests/form_pages/test_computed_field.py | ||
---|---|---|
631 | 631 | |
632 | 632 | |
633 | 633 |
def test_computed_field_with_bad_objects_filter_in_prefill(pub): |
634 |
if pub.is_using_postgresql(): |
|
635 |
pub.loggederror_class.wipe() |
|
634 |
pub.loggederror_class.wipe() |
|
636 | 635 |
CardDef.wipe() |
637 | 636 |
FormDef.wipe() |
638 | 637 | |
... | ... | |
676 | 675 |
formdef.store() |
677 | 676 |
resp = get_app(pub).get('/test/') |
678 | 677 |
assert 'XY' in resp.text |
679 |
if pub.is_using_postgresql(): |
|
680 |
assert pub.loggederror_class.count() == 2 |
|
681 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
682 |
assert logged_error.summary == 'wcs.carddef.CardDefDoesNotExist: unknown' |
|
683 |
assert logged_error.formdef_id == formdef.id |
|
684 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
685 |
assert ( |
|
686 |
logged_error.summary |
|
687 |
== 'Invalid value "{{ cards|objects:"unknown"|first|get:"form_number_raw"|default:"" }}" for field "computed"' |
|
688 |
) |
|
689 |
assert logged_error.formdef_id == formdef.id |
|
678 |
assert pub.loggederror_class.count() == 2 |
|
679 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
680 |
assert logged_error.summary == 'wcs.carddef.CardDefDoesNotExist: unknown' |
|
681 |
assert logged_error.formdef_id == formdef.id |
|
682 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
683 |
assert ( |
|
684 |
logged_error.summary |
|
685 |
== 'Invalid value "{{ cards|objects:"unknown"|first|get:"form_number_raw"|default:"" }}" for field "computed"' |
|
686 |
) |
|
687 |
assert logged_error.formdef_id == formdef.id |
|
690 | 688 | |
691 | 689 | |
692 | 690 |
def test_computed_field_with_bad_value_type_in_prefill(pub): |
693 |
if pub.is_using_postgresql(): |
|
694 |
pub.loggederror_class.wipe() |
|
691 |
pub.loggederror_class.wipe() |
|
695 | 692 |
CardDef.wipe() |
696 | 693 |
FormDef.wipe() |
697 | 694 | |
... | ... | |
740 | 737 |
formdef.store() |
741 | 738 |
resp = get_app(pub).get('/test/') |
742 | 739 |
assert 'XY' in resp.text |
743 |
if pub.is_using_postgresql(): |
|
744 |
assert pub.loggederror_class.count() == 1 |
|
745 |
logged_error = pub.loggederror_class.select()[0] |
|
746 |
assert logged_error.summary == 'Invalid value "foo" for field "computed"' |
|
747 |
assert logged_error.formdef_id == formdef.id |
|
740 |
assert pub.loggederror_class.count() == 1 |
|
741 |
logged_error = pub.loggederror_class.select()[0] |
|
742 |
assert logged_error.summary == 'Invalid value "foo" for field "computed"' |
|
743 |
assert logged_error.formdef_id == formdef.id |
|
748 | 744 | |
749 | 745 |
formdef.fields[0].value_template = ( |
750 | 746 |
'{{ cards|objects:"%s"|first|get:"form_var_bool"|default:"" }}' % carddef.url_name |
... | ... | |
752 | 748 |
formdef.store() |
753 | 749 |
resp = get_app(pub).get('/test/') |
754 | 750 |
assert 'XY' in resp.text |
755 |
if pub.is_using_postgresql(): |
|
756 |
assert pub.loggederror_class.count() == 2 |
|
757 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
758 |
assert logged_error.summary == 'Invalid value "True" for field "computed"' |
|
759 |
assert logged_error.formdef_id == formdef.id |
|
751 |
assert pub.loggederror_class.count() == 2 |
|
752 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
753 |
assert logged_error.summary == 'Invalid value "True" for field "computed"' |
|
754 |
assert logged_error.formdef_id == formdef.id |
|
760 | 755 | |
761 | 756 |
for value_template in [ |
762 | 757 |
'{{ cards|objects:"%s"|get:42|get:"form_number_raw" }}' % carddef.url_name, |
... | ... | |
766 | 761 |
formdef.store() |
767 | 762 |
resp = get_app(pub).get('/test/') |
768 | 763 |
assert 'XY' in resp.text |
769 |
if pub.is_using_postgresql(): |
|
770 |
assert pub.loggederror_class.count() == 2 |
|
764 |
assert pub.loggederror_class.count() == 2 |
tests/form_pages/test_file_field.py | ||
---|---|---|
392 | 392 |
formdef.store() |
393 | 393 | |
394 | 394 |
get_app(pub).get('/test/') |
395 |
if pub.is_using_postgresql(): |
|
396 |
assert pub.loggederror_class.count() == 1 |
|
397 |
logged_error = pub.loggederror_class.select()[0] |
|
398 |
assert logged_error.formdef_id == formdef.id |
|
399 |
assert logged_error.summary == 'Failed to set value on field "file"' |
|
400 |
assert logged_error.exception_class == 'AttributeError' |
|
401 |
assert logged_error.exception_message == "'str' object has no attribute 'time'" |
|
395 |
assert pub.loggederror_class.count() == 1 |
|
396 |
logged_error = pub.loggederror_class.select()[0] |
|
397 |
assert logged_error.formdef_id == formdef.id |
|
398 |
assert logged_error.summary == 'Failed to set value on field "file"' |
|
399 |
assert logged_error.exception_class == 'AttributeError' |
|
400 |
assert logged_error.exception_message == "'str' object has no attribute 'time'" |
tests/form_pages/test_formdata.py | ||
---|---|---|
780 | 780 |
http_post_request.return_value = None, 400, '{"code": "document-exists"}', None # fail |
781 | 781 |
resp = resp.form.submit('button_export_to') |
782 | 782 |
assert http_post_request.call_count == 1 |
783 |
if pub.is_using_postgresql(): |
|
784 |
error = pub.loggederror_class.select()[0] |
|
785 |
assert error.summary.startswith("file 'template.pdf' failed to be pushed to portfolio of 'Foo") |
|
786 |
assert 'status: 400' in error.summary |
|
787 |
assert "payload: {'code': 'document-exists'}" in error.summary |
|
783 |
error = pub.loggederror_class.select()[0] |
|
784 |
assert error.summary.startswith("file 'template.pdf' failed to be pushed to portfolio of 'Foo") |
|
785 |
assert 'status: 400' in error.summary |
|
786 |
assert "payload: {'code': 'document-exists'}" in error.summary |
|
788 | 787 | |
789 | 788 |
# failed to push to portfolio, but document is here |
790 | 789 |
resp = resp.follow() # $form/$id/create_doc |
tests/form_pages/test_live.py | ||
---|---|---|
1320 | 1320 | |
1321 | 1321 |
@pytest.mark.parametrize('field_type', ['item', 'string', 'email']) |
1322 | 1322 |
def test_dynamic_item_field_from_custom_view_on_cards(pub, field_type): |
1323 |
if not pub.is_using_postgresql(): |
|
1324 |
pytest.skip('this requires SQL') |
|
1325 |
return |
|
1326 | ||
1327 | 1323 |
pub.role_class.wipe() |
1328 | 1324 |
pub.custom_view_class.wipe() |
1329 | 1325 | |
... | ... | |
1461 | 1457 |
assert formdef.data_class().select()[0].data['1_structured']['item'] == 'baz' |
1462 | 1458 | |
1463 | 1459 |
# delete custom view |
1464 |
if pub.is_using_postgresql(): |
|
1465 |
pub.loggederror_class.wipe() |
|
1460 |
pub.loggederror_class.wipe() |
|
1466 | 1461 |
custom_view.remove_self() |
1467 | 1462 |
resp = get_app(pub).get('/test/') |
1468 | 1463 |
assert resp.form['f1'].options == [] |
1469 |
if pub.is_using_postgresql(): |
|
1470 |
assert pub.loggederror_class.count() == 1 |
|
1471 |
logged_error = pub.loggederror_class.select()[0] |
|
1472 |
assert logged_error.formdef_id == formdef.id |
|
1473 |
assert logged_error.summary == '[DATASOURCE] Unknown custom view "as-data-source" for CardDef "items"' |
|
1464 |
assert pub.loggederror_class.count() == 1 |
|
1465 |
logged_error = pub.loggederror_class.select()[0] |
|
1466 |
assert logged_error.formdef_id == formdef.id |
|
1467 |
assert logged_error.summary == '[DATASOURCE] Unknown custom view "as-data-source" for CardDef "items"' |
|
1474 | 1468 | |
1475 | 1469 | |
1476 | 1470 |
def test_dynamic_items_field_from_custom_view_on_cards(pub): |
1477 |
if not pub.is_using_postgresql(): |
|
1478 |
pytest.skip('this requires SQL') |
|
1479 |
return |
|
1480 | ||
1481 | 1471 |
pub.role_class.wipe() |
1482 | 1472 |
pub.custom_view_class.wipe() |
1483 | 1473 | |
... | ... | |
1606 | 1596 |
assert formdef.data_class().select()[0].data['1_structured']['text'] == 'attr1 - foo,bar' |
1607 | 1597 | |
1608 | 1598 |
# delete custom view |
1609 |
if pub.is_using_postgresql(): |
|
1610 |
pub.loggederror_class.wipe() |
|
1599 |
pub.loggederror_class.wipe() |
|
1611 | 1600 |
custom_view.remove_self() |
1612 | 1601 |
resp = get_app(pub).get('/test/') |
1613 | 1602 |
assert resp.form['f1'].options == [] |
1614 |
if pub.is_using_postgresql(): |
|
1615 |
assert pub.loggederror_class.count() == 1 |
|
1616 |
logged_error = pub.loggederror_class.select()[0] |
|
1617 |
assert logged_error.formdef_id == formdef.id |
|
1618 |
assert logged_error.summary == '[DATASOURCE] Unknown custom view "as-data-source" for CardDef "items"' |
|
1603 |
assert pub.loggederror_class.count() == 1 |
|
1604 |
logged_error = pub.loggederror_class.select()[0] |
|
1605 |
assert logged_error.formdef_id == formdef.id |
|
1606 |
assert logged_error.summary == '[DATASOURCE] Unknown custom view "as-data-source" for CardDef "items"' |
|
1619 | 1607 | |
1620 | 1608 | |
1621 | 1609 |
def test_dynamic_internal_id_from_custom_view_on_cards(pub): |
1622 |
if not pub.is_using_postgresql(): |
|
1623 |
pytest.skip('this requires SQL') |
|
1624 |
return |
|
1625 | ||
1626 | 1610 |
pub.role_class.wipe() |
1627 | 1611 |
pub.custom_view_class.wipe() |
1628 | 1612 |
tests/test_carddef.py | ||
---|---|---|
453 | 453 | |
454 | 454 |
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['Hello'] |
455 | 455 |
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == [] |
456 |
if pub.is_using_postgresql(): |
|
457 |
assert pub.loggederror_class.count() == 2 |
|
458 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
459 |
assert logged_error.summary == 'Invalid filter "42"' |
|
460 |
assert logged_error.formdef_id == str(carddef.id) |
|
461 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
462 |
assert logged_error.summary == 'Invalid filter "foobar"' |
|
463 |
assert logged_error.formdef_id == str(carddef.id) |
|
456 |
assert pub.loggederror_class.count() == 2 |
|
457 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
458 |
assert logged_error.summary == 'Invalid filter "42"' |
|
459 |
assert logged_error.formdef_id == str(carddef.id) |
|
460 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
461 |
assert logged_error.summary == 'Invalid filter "foobar"' |
|
462 |
assert logged_error.formdef_id == str(carddef.id) |
|
464 | 463 | |
465 | 464 | |
466 | 465 |
def test_data_source_anonymised_cards(pub): |
... | ... | |
600 | 599 |
carddef.store() |
601 | 600 |
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo')] == ['', ''] |
602 | 601 |
assert [i['text'] for i in CardDef.get_data_source_items('carddef:foo:view')] == ['', ''] |
603 |
if pub.is_using_postgresql(): |
|
604 |
assert pub.loggederror_class.count() == 2 |
|
605 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
606 |
assert logged_error.summary == 'Digest (default) not defined' |
|
607 |
assert logged_error.formdata_id in (str(carddata.id), str(carddata2.id)) |
|
608 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
609 |
assert logged_error.summary == 'Digest (custom view "view") not defined' |
|
610 |
assert logged_error.formdata_id in (str(carddata.id), str(carddata2.id)) |
|
602 |
assert pub.loggederror_class.count() == 2 |
|
603 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
604 |
assert logged_error.summary == 'Digest (default) not defined' |
|
605 |
assert logged_error.formdata_id in (str(carddata.id), str(carddata2.id)) |
|
606 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
607 |
assert logged_error.summary == 'Digest (custom view "view") not defined' |
|
608 |
assert logged_error.formdata_id in (str(carddata.id), str(carddata2.id)) |
|
611 | 609 |
assert CardDef.get_data_source_items('carddef:foo', get_by_text='') == [] |
612 | 610 |
assert CardDef.get_data_source_items('carddef:foo:view', get_by_text='') == [] |
613 | 611 |
tests/test_datasource.py | ||
---|---|---|
139 | 139 |
datasource = {'type': 'formula', 'value': 'foobar', 'notify_on_errors': True, 'record_on_errors': True} |
140 | 140 |
assert data_sources.get_items(datasource) == [] |
141 | 141 |
assert 'Failed to eval() Python data source' in emails.get_latest('subject') |
142 |
if pub.is_using_postgresql(): |
|
143 |
assert pub.loggederror_class.count() == 1 |
|
144 |
logged_error = pub.loggederror_class.select()[0] |
|
145 |
assert logged_error.workflow_id is None |
|
146 |
assert logged_error.summary == "[DATASOURCE] Failed to eval() Python data source ('foobar')" |
|
142 |
assert pub.loggederror_class.count() == 1 |
|
143 |
logged_error = pub.loggederror_class.select()[0] |
|
144 |
assert logged_error.workflow_id is None |
|
145 |
assert logged_error.summary == "[DATASOURCE] Failed to eval() Python data source ('foobar')" |
|
147 | 146 | |
148 | 147 |
# expression not iterable |
149 | 148 |
datasource = {'type': 'formula', 'value': '2', 'notify_on_errors': True, 'record_on_errors': True} |
150 | 149 |
assert data_sources.get_items(datasource) == [] |
151 | 150 |
assert 'gave a non-iterable result' in emails.get_latest('subject') |
152 |
if pub.is_using_postgresql(): |
|
153 |
assert pub.loggederror_class.count() == 2 |
|
154 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
155 |
assert logged_error.workflow_id is None |
|
156 |
assert logged_error.summary == "[DATASOURCE] Python data source ('2') gave a non-iterable result" |
|
151 |
assert pub.loggederror_class.count() == 2 |
|
152 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
153 |
assert logged_error.workflow_id is None |
|
154 |
assert logged_error.summary == "[DATASOURCE] Python data source ('2') gave a non-iterable result" |
|
157 | 155 | |
158 | 156 |
datasource = { |
159 | 157 |
'type': 'formula', |
... | ... | |
161 | 159 |
'record_on_errors': True, |
162 | 160 |
} |
163 | 161 |
assert data_sources.get_items(datasource) == [] |
164 |
if pub.is_using_postgresql(): |
|
165 |
assert pub.loggederror_class.count() == 3 |
|
166 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
167 |
assert logged_error.workflow_id is None |
|
168 |
assert logged_error.summary == ( |
|
169 |
'[DATASOURCE] Python data source (\'[{"mairie-a-rdv", "Mairie A"}, {"mairie-b-rdv", "Mairie B"}]\') gave a non usable result' |
|
170 |
) |
|
162 |
assert pub.loggederror_class.count() == 3 |
|
163 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
164 |
assert logged_error.workflow_id is None |
|
165 |
assert logged_error.summary == ( |
|
166 |
'[DATASOURCE] Python data source (\'[{"mairie-a-rdv", "Mairie A"}, {"mairie-b-rdv", "Mairie B"}]\') gave a non usable result' |
|
167 |
) |
|
171 | 168 | |
172 | 169 |
# list of dictionaries but some are missing a text key |
173 | 170 |
datasource = { |
... | ... | |
176 | 173 |
'record_on_errors': True, |
177 | 174 |
} |
178 | 175 |
assert data_sources.get_items(datasource) == [] |
179 |
if pub.is_using_postgresql(): |
|
180 |
assert pub.loggederror_class.count() == 4 |
|
181 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
182 |
assert logged_error.workflow_id is None |
|
183 |
assert logged_error.summary == ( |
|
184 |
'[DATASOURCE] Python data source (\'[{"mairie-a-rdv", "Mairie A"}, {"mairie-b-rdv", "Mairie B"}]\') gave a non usable result' |
|
185 |
) |
|
176 |
assert pub.loggederror_class.count() == 4 |
|
177 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
178 |
assert logged_error.workflow_id is None |
|
179 |
assert logged_error.summary == ( |
|
180 |
'[DATASOURCE] Python data source (\'[{"mairie-a-rdv", "Mairie A"}, {"mairie-b-rdv", "Mairie B"}]\') gave a non usable result' |
|
181 |
) |
|
186 | 182 | |
187 | 183 |
if not pub.site_options.has_section('options'): |
188 | 184 |
pub.site_options.add_section('options') |
... | ... | |
191 | 187 |
pub.site_options.write(fd) |
192 | 188 | |
193 | 189 |
# running with disabled python expressions |
194 |
if pub.is_using_postgresql(): |
|
195 |
pub.loggederror_class.wipe() |
|
190 |
pub.loggederror_class.wipe() |
|
196 | 191 |
datasource = { |
197 | 192 |
'type': 'formula', |
198 | 193 |
'value': repr(['foo', 'bar']), |
... | ... | |
203 | 198 |
assert data_sources.get_items(datasource) == [] |
204 | 199 |
assert emails.count() == 1 # notified even with notify_on_errors set to False |
205 | 200 |
assert 'Unauthorized Python Usage' in emails.get_latest('subject') |
206 |
if pub.is_using_postgresql(): |
|
207 |
assert pub.loggederror_class.count() == 1 |
|
208 |
logged_error = pub.loggederror_class.select(order_by='latest_occurence_timestamp')[-1] |
|
209 |
assert logged_error.workflow_id is None |
|
210 |
assert logged_error.summary == 'Unauthorized Python Usage' |
|
201 |
assert pub.loggederror_class.count() == 1 |
|
202 |
logged_error = pub.loggederror_class.select(order_by='latest_occurence_timestamp')[-1] |
|
203 |
assert logged_error.workflow_id is None |
|
204 |
assert logged_error.summary == 'Unauthorized Python Usage' |
|
211 | 205 | |
212 | 206 | |
213 | 207 |
def test_python_datasource_with_evalutils(pub): |
... | ... | |
450 | 444 |
assert 'error in HTTP request to http://remote.example.net/404 (status: 404)' in emails.get_latest( |
451 | 445 |
'subject' |
452 | 446 |
) |
453 |
if pub.is_using_postgresql(): |
|
454 |
assert pub.loggederror_class.count() == 1 |
|
455 |
logged_error = pub.loggederror_class.select()[0] |
|
456 |
assert logged_error.workflow_id is None |
|
457 |
assert ( |
|
458 |
logged_error.summary |
|
459 |
== "[DATASOURCE] Error loading JSON data source (error in HTTP request to http://remote.example.net/404 (status: 404))" |
|
460 |
) |
|
447 |
assert pub.loggederror_class.count() == 1 |
|
448 |
logged_error = pub.loggederror_class.select()[0] |
|
449 |
assert logged_error.workflow_id is None |
|
450 |
assert ( |
|
451 |
logged_error.summary |
|
452 |
== "[DATASOURCE] Error loading JSON data source (error in HTTP request to http://remote.example.net/404 (status: 404))" |
|
453 |
) |
|
461 | 454 | |
462 | 455 |
datasource = { |
463 | 456 |
'type': 'json', |
... | ... | |
468 | 461 |
assert data_sources.get_items(datasource) == [] |
469 | 462 |
assert emails.count() == 2 |
470 | 463 |
assert 'Error reading JSON data source' in emails.get_latest('subject') |
471 |
if pub.is_using_postgresql(): |
|
472 |
assert pub.loggederror_class.count() == 2 |
|
473 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
474 |
assert logged_error.workflow_id is None |
|
475 |
assert ( |
|
476 |
logged_error.summary |
|
477 |
== "[DATASOURCE] Error reading JSON data source output (Expecting value: line 1 column 1 (char 0))" |
|
478 |
) |
|
464 |
assert pub.loggederror_class.count() == 2 |
|
465 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
466 |
assert logged_error.workflow_id is None |
|
467 |
assert ( |
|
468 |
logged_error.summary |
|
469 |
== "[DATASOURCE] Error reading JSON data source output (Expecting value: line 1 column 1 (char 0))" |
|
470 |
) |
|
479 | 471 | |
480 | 472 |
datasource = { |
481 | 473 |
'type': 'json', |
... | ... | |
485 | 477 |
} |
486 | 478 |
assert data_sources.get_items(datasource) == [] |
487 | 479 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
488 |
if pub.is_using_postgresql(): |
|
489 |
assert pub.loggederror_class.count() == 3 |
|
490 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
491 |
assert logged_error.workflow_id is None |
|
492 |
assert logged_error.summary == "[DATASOURCE] Error loading JSON data source (error)" |
|
480 |
assert pub.loggederror_class.count() == 3 |
|
481 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
482 |
assert logged_error.workflow_id is None |
|
483 |
assert logged_error.summary == "[DATASOURCE] Error loading JSON data source (error)" |
|
493 | 484 | |
494 | 485 |
datasource = { |
495 | 486 |
'type': 'json', |
... | ... | |
499 | 490 |
} |
500 | 491 |
assert data_sources.get_items(datasource) == [] |
501 | 492 |
assert 'Error reading JSON data source output (err 1)' in emails.get_latest('subject') |
502 |
if pub.is_using_postgresql(): |
|
503 |
assert pub.loggederror_class.count() == 4 |
|
504 |
logged_error = pub.loggederror_class.select(order_by='id')[3] |
|
505 |
assert logged_error.workflow_id is None |
|
506 |
assert logged_error.summary == "[DATASOURCE] Error reading JSON data source output (err 1)" |
|
493 |
assert pub.loggederror_class.count() == 4 |
|
494 |
logged_error = pub.loggederror_class.select(order_by='id')[3] |
|
495 |
assert logged_error.workflow_id is None |
|
496 |
assert logged_error.summary == "[DATASOURCE] Error reading JSON data source output (err 1)" |
|
507 | 497 | |
508 | 498 | |
509 | 499 |
def test_json_datasource_bad_url_scheme(pub, error_email, emails): |
510 | 500 |
datasource = {'type': 'json', 'value': '', 'notify_on_errors': True, 'record_on_errors': True} |
511 | 501 |
assert data_sources.get_items(datasource) == [] |
512 | 502 |
assert emails.count() == 0 |
513 |
if pub.is_using_postgresql(): |
|
514 |
assert pub.loggederror_class.count() == 0 |
|
503 |
assert pub.loggederror_class.count() == 0 |
|
515 | 504 | |
516 | 505 |
datasource = {'type': 'json', 'value': 'foo://bar', 'notify_on_errors': True, 'record_on_errors': True} |
517 | 506 |
assert data_sources.get_items(datasource) == [] |
518 | 507 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
519 | 508 |
assert 'invalid scheme in URL' in emails.get_latest('subject') |
520 |
if pub.is_using_postgresql(): |
|
521 |
assert pub.loggederror_class.count() == 1 |
|
522 |
logged_error = pub.loggederror_class.select()[0] |
|
523 |
assert logged_error.workflow_id is None |
|
524 |
assert ( |
|
525 |
logged_error.summary |
|
526 |
== "[DATASOURCE] Error loading JSON data source (invalid scheme in URL foo://bar)" |
|
527 |
) |
|
509 |
assert pub.loggederror_class.count() == 1 |
|
510 |
logged_error = pub.loggederror_class.select()[0] |
|
511 |
assert logged_error.workflow_id is None |
|
512 |
assert ( |
|
513 |
logged_error.summary |
|
514 |
== "[DATASOURCE] Error loading JSON data source (invalid scheme in URL foo://bar)" |
|
515 |
) |
|
528 | 516 | |
529 | 517 |
datasource = {'type': 'json', 'value': '/bla/blo', 'notify_on_errors': True, 'record_on_errors': True} |
530 | 518 |
assert data_sources.get_items(datasource) == [] |
531 | 519 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
532 | 520 |
assert 'invalid scheme in URL' in emails.get_latest('subject') |
533 |
if pub.is_using_postgresql(): |
|
534 |
assert pub.loggederror_class.count() == 2 |
|
535 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
536 |
assert logged_error.workflow_id is None |
|
537 |
assert ( |
|
538 |
logged_error.summary |
|
539 |
== "[DATASOURCE] Error loading JSON data source (invalid scheme in URL /bla/blo)" |
|
540 |
) |
|
521 |
assert pub.loggederror_class.count() == 2 |
|
522 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
523 |
assert logged_error.workflow_id is None |
|
524 |
assert ( |
|
525 |
logged_error.summary == "[DATASOURCE] Error loading JSON data source (invalid scheme in URL /bla/blo)" |
|
526 |
) |
|
541 | 527 | |
542 | 528 | |
543 | 529 |
@pytest.mark.parametrize('notify', [True, False]) |
... | ... | |
561 | 547 |
assert message in emails.get_latest('subject') |
562 | 548 |
else: |
563 | 549 |
assert emails.count() == 0 |
564 |
if pub.is_using_postgresql(): |
|
565 |
if record: |
|
566 |
assert pub.loggederror_class.count() == 1 |
|
567 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
568 |
assert logged_error.summary == message |
|
569 |
else: |
|
570 |
assert pub.loggederror_class.count() == 0 |
|
550 |
if record: |
|
551 |
assert pub.loggederror_class.count() == 1 |
|
552 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
553 |
assert logged_error.summary == message |
|
554 |
else: |
|
555 |
assert pub.loggederror_class.count() == 0 |
|
571 | 556 | |
572 | 557 | |
573 | 558 |
def test_geojson_datasource(pub, requests_pub, http_requests): |
... | ... | |
896 | 881 |
assert data_sources.get_items(datasource) == [] |
897 | 882 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
898 | 883 |
assert 'status: 404' in emails.get_latest('subject') |
899 |
if pub.is_using_postgresql(): |
|
900 |
assert pub.loggederror_class.count() == 1 |
|
901 |
logged_error = pub.loggederror_class.select()[0] |
|
902 |
assert logged_error.workflow_id is None |
|
903 |
assert ( |
|
904 |
logged_error.summary |
|
905 |
== "[DATASOURCE] Error loading JSON data source (error in HTTP request to http://remote.example.net/404 (status: 404))" |
|
906 |
) |
|
884 |
assert pub.loggederror_class.count() == 1 |
|
885 |
logged_error = pub.loggederror_class.select()[0] |
|
886 |
assert logged_error.workflow_id is None |
|
887 |
assert ( |
|
888 |
logged_error.summary |
|
889 |
== "[DATASOURCE] Error loading JSON data source (error in HTTP request to http://remote.example.net/404 (status: 404))" |
|
890 |
) |
|
907 | 891 | |
908 | 892 |
datasource = { |
909 | 893 |
'type': 'geojson', |
... | ... | |
914 | 898 |
assert data_sources.get_items(datasource) == [] |
915 | 899 |
assert 'Error reading JSON data source output' in emails.get_latest('subject') |
916 | 900 |
assert 'Expecting value:' in emails.get_latest('subject') |
917 |
if pub.is_using_postgresql(): |
|
918 |
assert pub.loggederror_class.count() == 2 |
|
919 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
920 |
assert logged_error.workflow_id is None |
|
921 |
assert ( |
|
922 |
logged_error.summary |
|
923 |
== "[DATASOURCE] Error reading JSON data source output (Expecting value: line 1 column 1 (char 0))" |
|
924 |
) |
|
901 |
assert pub.loggederror_class.count() == 2 |
|
902 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
903 |
assert logged_error.workflow_id is None |
|
904 |
assert ( |
|
905 |
logged_error.summary |
|
906 |
== "[DATASOURCE] Error reading JSON data source output (Expecting value: line 1 column 1 (char 0))" |
|
907 |
) |
|
925 | 908 | |
926 | 909 |
datasource = { |
927 | 910 |
'type': 'geojson', |
... | ... | |
932 | 915 |
assert data_sources.get_items(datasource) == [] |
933 | 916 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
934 | 917 |
assert 'error' in emails.get_latest('subject') |
935 |
if pub.is_using_postgresql(): |
|
936 |
assert pub.loggederror_class.count() == 3 |
|
937 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
938 |
assert logged_error.workflow_id is None |
|
939 |
assert logged_error.summary == "[DATASOURCE] Error loading JSON data source (error)" |
|
918 |
assert pub.loggederror_class.count() == 3 |
|
919 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
920 |
assert logged_error.workflow_id is None |
|
921 |
assert logged_error.summary == "[DATASOURCE] Error loading JSON data source (error)" |
|
940 | 922 | |
941 | 923 |
datasource = { |
942 | 924 |
'type': 'geojson', |
... | ... | |
946 | 928 |
} |
947 | 929 |
assert data_sources.get_items(datasource) == [] |
948 | 930 |
assert 'Error reading JSON data source output (err 1)' in emails.get_latest('subject') |
949 |
if pub.is_using_postgresql(): |
|
950 |
assert pub.loggederror_class.count() == 4 |
|
951 |
logged_error = pub.loggederror_class.select(order_by='id')[3] |
|
952 |
assert logged_error.workflow_id is None |
|
953 |
assert logged_error.summary == "[DATASOURCE] Error reading JSON data source output (err 1)" |
|
931 |
assert pub.loggederror_class.count() == 4 |
|
932 |
logged_error = pub.loggederror_class.select(order_by='id')[3] |
|
933 |
assert logged_error.workflow_id is None |
|
934 |
assert logged_error.summary == "[DATASOURCE] Error reading JSON data source output (err 1)" |
|
954 | 935 | |
955 | 936 | |
956 | 937 |
def test_geojson_datasource_bad_url_scheme(pub, error_email, emails): |
... | ... | |
962 | 943 |
assert data_sources.get_items(datasource) == [] |
963 | 944 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
964 | 945 |
assert 'invalid scheme in URL' in emails.get_latest('subject') |
965 |
if pub.is_using_postgresql(): |
|
966 |
assert pub.loggederror_class.count() == 1 |
|
967 |
logged_error = pub.loggederror_class.select()[0] |
|
968 |
assert logged_error.workflow_id is None |
|
969 |
assert ( |
|
970 |
logged_error.summary |
|
971 |
== "[DATASOURCE] Error loading JSON data source (invalid scheme in URL foo://bar)" |
|
972 |
) |
|
946 |
assert pub.loggederror_class.count() == 1 |
|
947 |
logged_error = pub.loggederror_class.select()[0] |
|
948 |
assert logged_error.workflow_id is None |
|
949 |
assert ( |
|
950 |
logged_error.summary |
|
951 |
== "[DATASOURCE] Error loading JSON data source (invalid scheme in URL foo://bar)" |
|
952 |
) |
|
973 | 953 | |
974 | 954 |
datasource = {'type': 'geojson', 'value': '/bla/blo', 'notify_on_errors': True, 'record_on_errors': True} |
975 | 955 |
assert data_sources.get_items(datasource) == [] |
976 | 956 |
assert 'Error loading JSON data source' in emails.get_latest('subject') |
977 | 957 |
assert 'invalid scheme in URL' in emails.get_latest('subject') |
978 |
if pub.is_using_postgresql(): |
|
979 |
assert pub.loggederror_class.count() == 2 |
|
980 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
981 |
assert logged_error.workflow_id is None |
|
982 |
assert ( |
|
983 |
logged_error.summary |
|
984 |
== "[DATASOURCE] Error loading JSON data source (invalid scheme in URL /bla/blo)" |
|
985 |
) |
|
958 |
assert pub.loggederror_class.count() == 2 |
|
959 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
960 |
assert logged_error.workflow_id is None |
|
961 |
assert ( |
|
962 |
logged_error.summary == "[DATASOURCE] Error loading JSON data source (invalid scheme in URL /bla/blo)" |
|
963 |
) |
|
986 | 964 | |
987 | 965 | |
988 | 966 |
def test_item_field_named_python_datasource(requests_pub): |
tests/test_fc_auth.py | ||
---|---|---|
193 | 193 |
} |
194 | 194 |
) |
195 | 195 |
) |
196 |
if pub.is_using_postgresql(): |
|
197 |
assert 'user did not authorize login' in pub.loggederror_class.select(order_by='id')[-1].summary |
|
196 |
assert 'user did not authorize login' in pub.loggederror_class.select(order_by='id')[-1].summary |
|
198 | 197 |
resp = app.get( |
199 | 198 |
'/ident/fc/callback?%s' |
200 | 199 |
% urllib.parse.urlencode( |
... | ... | |
204 | 203 |
} |
205 | 204 |
) |
206 | 205 |
) |
207 |
if pub.is_using_postgresql(): |
|
208 |
assert 'whatever' in pub.loggederror_class.select(order_by='id')[-1].summary |
|
206 |
assert 'whatever' in pub.loggederror_class.select(order_by='id')[-1].summary |
|
209 | 207 | |
210 | 208 |
# Login existing user |
211 | 209 |
def logme(login_url): |
tests/test_formdata.py | ||
---|---|---|
1250 | 1250 |
assert queryset.count == 4 |
1251 | 1251 |
queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('X') |
1252 | 1252 |
assert queryset.count == 0 |
1253 |
if pub.is_using_postgresql(): |
|
1254 |
pub.loggederror_class.wipe() |
|
1253 |
pub.loggederror_class.wipe() |
|
1255 | 1254 |
queryset = lazy_formdata.objects.filter_by('unknown').apply_filter_value('X') |
1256 | 1255 |
assert queryset.count == 0 |
1257 |
if pub.is_using_postgresql(): |
|
1258 |
assert pub.loggederror_class.count() == 1 |
|
1259 |
logged_error = pub.loggederror_class.select()[0] |
|
1260 |
assert logged_error.summary == 'Invalid filter "unknown"' |
|
1256 |
assert pub.loggederror_class.count() == 1 |
|
1257 |
logged_error = pub.loggederror_class.select()[0] |
|
1258 |
assert logged_error.summary == 'Invalid filter "unknown"' |
|
1261 | 1259 | |
1262 | 1260 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_filter_value( |
1263 | 1261 |
datetime.date(2018, 7, 31).timetuple() |
... | ... | |
1273 | 1271 |
assert queryset.count == 5 |
1274 | 1272 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_filter_value('not a date') |
1275 | 1273 |
assert queryset.count == 0 |
1276 |
if pub.is_using_postgresql(): |
|
1277 |
assert pub.loggederror_class.count() == 2 |
|
1278 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
1279 |
assert logged_error.summary == 'Invalid value "not a date" for filter "datefield"' |
|
1280 | ||
1281 |
if pub.is_using_postgresql(): |
|
1282 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value( |
|
1283 |
datetime.date(2018, 7, 31).timetuple() |
|
1284 |
) |
|
1285 |
assert queryset.count == 6 # 1 + 5 null |
|
1286 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value( |
|
1287 |
datetime.date(2018, 7, 31) |
|
1288 |
) |
|
1289 |
assert queryset.count == 6 |
|
1290 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value( |
|
1291 |
datetime.datetime(2018, 7, 31) |
|
1292 |
) |
|
1293 |
assert queryset.count == 6 |
|
1294 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value('2018-07-31') |
|
1295 |
assert queryset.count == 6 |
|
1296 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value(None) |
|
1297 |
assert queryset.count == 6 |
|
1298 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value('still not a date') |
|
1299 |
assert queryset.count == 0 |
|
1300 |
assert pub.loggederror_class.count() == 3 |
|
1301 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
1302 |
assert logged_error.summary == 'Invalid value "still not a date" for filter "datefield"' |
|
1274 |
assert pub.loggederror_class.count() == 2 |
|
1275 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
1276 |
assert logged_error.summary == 'Invalid value "not a date" for filter "datefield"' |
|
1277 | ||
1278 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value( |
|
1279 |
datetime.date(2018, 7, 31).timetuple() |
|
1280 |
) |
|
1281 |
assert queryset.count == 6 # 1 + 5 null |
|
1282 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value(datetime.date(2018, 7, 31)) |
|
1283 |
assert queryset.count == 6 |
|
1284 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value( |
|
1285 |
datetime.datetime(2018, 7, 31) |
|
1286 |
) |
|
1287 |
assert queryset.count == 6 |
|
1288 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value('2018-07-31') |
|
1289 |
assert queryset.count == 6 |
|
1290 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value(None) |
|
1291 |
assert queryset.count == 6 |
|
1292 |
queryset = lazy_formdata.objects.filter_by('datefield').apply_exclude_value('still not a date') |
|
1293 |
assert queryset.count == 0 |
|
1294 |
assert pub.loggederror_class.count() == 3 |
|
1295 |
logged_error = pub.loggederror_class.select(order_by='id')[2] |
|
1296 |
assert logged_error.summary == 'Invalid value "still not a date" for filter "datefield"' |
|
1303 | 1297 | |
1304 | 1298 |
queryset = lazy_formdata.objects.filter_by('boolfield').apply_filter_value(True) |
1305 | 1299 |
assert queryset.count == 6 |
... | ... | |
1311 | 1305 |
assert queryset.count == 5 |
1312 | 1306 |
queryset = lazy_formdata.objects.filter_by('boolfield').apply_filter_value(0) |
1313 | 1307 |
assert queryset.count == 5 |
1314 |
if pub.is_using_postgresql(): |
|
1315 |
queryset = lazy_formdata.objects.filter_by('boolfield').apply_exclude_value(0) |
|
1316 |
assert queryset.count == 6 |
|
1308 |
queryset = lazy_formdata.objects.filter_by('boolfield').apply_exclude_value(0) |
|
1309 |
assert queryset.count == 6 |
|
1317 | 1310 | |
1318 | 1311 |
queryset = lazy_formdata.objects.filter_by('term1').apply_filter_value('3') |
1319 | 1312 |
assert queryset.count == 7 |
... | ... | |
1321 | 1314 |
assert queryset.count == 7 |
1322 | 1315 |
queryset = lazy_formdata.objects.filter_by('term1').apply_filter_value('foobar') |
1323 | 1316 |
assert queryset.count == 0 |
1324 |
if pub.is_using_postgresql(): |
|
1325 |
queryset = lazy_formdata.objects.filter_by('term1').apply_exclude_value('3') |
|
1326 |
assert queryset.count == 4 |
|
1327 |
queryset = lazy_formdata.objects.filter_by('term1').apply_exclude_value('foobar') |
|
1328 |
assert queryset.count == 11 |
|
1317 |
queryset = lazy_formdata.objects.filter_by('term1').apply_exclude_value('3') |
|
1318 |
assert queryset.count == 4 |
|
1319 |
queryset = lazy_formdata.objects.filter_by('term1').apply_exclude_value('foobar') |
|
1320 |
assert queryset.count == 11 |
|
1329 | 1321 | |
1330 | 1322 |
queryset = lazy_formdata.objects.filter_by('email').apply_filter_value('bar') |
1331 | 1323 |
assert queryset.count == 0 |
... | ... | |
1382 | 1374 |
assert tmpl.render(context) == '7' |
1383 | 1375 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|filter_value:"bar"|length}}') |
1384 | 1376 |
assert tmpl.render(context) == '7' |
1385 |
if pub.is_using_postgresql(): |
|
1386 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|exclude_value:"bar"|count}}') |
|
1387 |
assert tmpl.render(context) == '4' |
|
1388 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|exclude_value:"bar"|length}}') |
|
1389 |
assert tmpl.render(context) == '4' |
|
1377 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|exclude_value:"bar"|count}}') |
|
1378 |
assert tmpl.render(context) == '4' |
|
1379 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|exclude_value:"bar"|length}}') |
|
1380 |
assert tmpl.render(context) == '4' |
|
1390 | 1381 | |
1391 | 1382 |
pub.substitutions.feed(formdata) |
1392 | 1383 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|filter_value:form_var_foo_foo|count}}') |
... | ... | |
1397 | 1388 |
assert tmpl.render(context) == '5' |
1398 | 1389 |
tmpl = Template('{{form_objects|filter_by:"term1"|filter_value:form_var_term1|count}}') |
1399 | 1390 |
assert tmpl.render(context) == '7' |
1400 |
if pub.is_using_postgresql(): |
|
1401 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|exclude_value:form_var_foo_foo|count}}') |
|
1402 |
assert tmpl.render(context) == '4' |
|
1403 |
tmpl = Template('{{form_objects|filter_by:"datefield"|exclude_value:form_var_datefield|count}}') |
|
1404 |
assert tmpl.render(context) == '6' |
|
1405 |
tmpl = Template('{{form_objects|filter_by:"boolfield"|exclude_value:form_var_boolfield|count}}') |
|
1406 |
assert tmpl.render(context) == '6' |
|
1407 |
tmpl = Template('{{form_objects|filter_by:"term1"|exclude_value:form_var_term1|count}}') |
|
1408 |
assert tmpl.render(context) == '4' |
|
1391 |
tmpl = Template('{{form_objects|filter_by:"foo_foo"|exclude_value:form_var_foo_foo|count}}') |
|
1392 |
assert tmpl.render(context) == '4' |
|
1393 |
tmpl = Template('{{form_objects|filter_by:"datefield"|exclude_value:form_var_datefield|count}}') |
|
1394 |
assert tmpl.render(context) == '6' |
|
1395 |
tmpl = Template('{{form_objects|filter_by:"boolfield"|exclude_value:form_var_boolfield|count}}') |
|
1396 |
assert tmpl.render(context) == '6' |
|
1397 |
tmpl = Template('{{form_objects|filter_by:"term1"|exclude_value:form_var_term1|count}}') |
|
1398 |
assert tmpl.render(context) == '4' |
|
1409 | 1399 | |
1410 | 1400 |
tmpl = Template('{{form.objects|exclude_self|filter_by:"foo_foo"|filter_value:form_var_foo_foo|count}}') |
1411 | 1401 |
assert tmpl.render(context) == '6' |
... | ... | |
1484 | 1474 |
assert tmpl.render(context) == '0' |
1485 | 1475 |
tmpl = Template('{{form_objects|filter_by_internal_id:"%s"|count}}' % 'invalid value') |
1486 | 1476 |
assert tmpl.render(context) == '0' |
1487 |
if pub.is_using_postgresql(): |
|
1488 |
assert pub.loggederror_class.count() == 4 |
|
1489 |
logged_error = pub.loggederror_class.select(order_by='id')[3] |
|
1490 |
assert logged_error.summary == 'Invalid value "invalid value" for "filter_by_internal_id"' |
|
1477 |
assert pub.loggederror_class.count() == 4 |
|
1478 |
logged_error = pub.loggederror_class.select(order_by='id')[3] |
|
1479 |
assert logged_error.summary == 'Invalid value "invalid value" for "filter_by_internal_id"' |
|
1491 | 1480 | |
1492 | 1481 |
# test |filter_by_number |
1493 | 1482 |
context = pub.substitutions.get_context_variables(mode='lazy') |
... | ... | |
1665 | 1654 | |
1666 | 1655 | |
1667 | 1656 |
def test_lazy_formdata_queryset_order_by(pub, variable_test_data): |
1668 |
if not pub.is_using_postgresql(): |
|
1669 |
pytest.skip('this requires SQL') |
|
1670 | ||
1671 | 1657 |
lazy_formdata = variable_test_data |
1672 | 1658 |
data_class = lazy_formdata._formdef.data_class() |
1673 | 1659 |
for i in range(6): |
... | ... | |
1818 | 1804 |
custom_view4.store() |
1819 | 1805 |
tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"unknown-filter"|count}}') |
1820 | 1806 |
assert tmpl.render(context) == '0' |
1821 |
if pub.is_using_postgresql(): |
|
1822 |
assert pub.loggederror_class.count() == 2 |
|
1823 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
1824 |
assert logged_error.summary == 'Invalid filter "42"' |
|
1825 |
assert logged_error.formdef_id == str(formdef.id) |
|
1826 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
1827 |
assert logged_error.summary == 'Invalid filter "foobar"' |
|
1828 |
assert logged_error.formdef_id == str(formdef.id) |
|
1807 |
assert pub.loggederror_class.count() == 2 |
|
1808 |
logged_error = pub.loggederror_class.select(order_by='id')[0] |
|
1809 |
assert logged_error.summary == 'Invalid filter "42"' |
|
1810 |
assert logged_error.formdef_id == str(formdef.id) |
|
1811 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
1812 |
assert logged_error.summary == 'Invalid filter "foobar"' |
|
1813 |
assert logged_error.formdef_id == str(formdef.id) |
|
1829 | 1814 | |
1830 | 1815 | |
1831 | 1816 |
def test_lazy_variables(pub, variable_test_data): |
... | ... | |
2664 | 2649 |
formdata.store() |
2665 | 2650 |
assert formdef.data_class().get(formdata.id).digests['default'] == 'ERROR' |
2666 | 2651 | |
2667 |
if pub.is_using_postgresql(): |
|
2668 |
assert pub.loggederror_class.count() == 1 |
|
2669 |
logged_error = pub.loggederror_class.select()[0] |
|
2670 |
assert logged_error.summary == 'Could not render digest (default)' |
|
2671 |
assert logged_error.formdata_id == str(formdata.id) |
|
2652 |
assert pub.loggederror_class.count() == 1 |
|
2653 |
logged_error = pub.loggederror_class.select()[0] |
|
2654 |
assert logged_error.summary == 'Could not render digest (default)' |
|
2655 |
assert logged_error.formdata_id == str(formdata.id) |
|
2672 | 2656 | |
2673 | 2657 |
formdef.digest_templates = { |
2674 | 2658 |
'default': 'plop plop', |
... | ... | |
2680 | 2664 |
formdata.store() |
2681 | 2665 |
assert formdef.data_class().get(formdata.id).digests['custom-view:foobar'] == 'ERROR' |
2682 | 2666 | |
2683 |
if pub.is_using_postgresql(): |
|
2684 |
assert pub.loggederror_class.count() == 2 |
|
2685 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
2686 |
assert logged_error.summary == 'Could not render digest (custom view "foobar")' |
|
2687 |
assert logged_error.formdata_id == str(formdata.id) |
|
2667 |
assert pub.loggederror_class.count() == 2 |
|
2668 |
logged_error = pub.loggederror_class.select(order_by='id')[1] |
|
2669 |
assert logged_error.summary == 'Could not render digest (custom view "foobar")' |
|
2670 |
assert logged_error.formdata_id == str(formdata.id) |
|
2688 | 2671 | |
2689 | 2672 | |
2690 | 2673 |
def test_lazy_formdata_decimal_filter(pub): |
tests/test_formdef.py | ||
---|---|---|
121 | 121 |
assert FormDef.get(formdef.id).url_name == 'foo' |
122 | 122 |
assert FormDef.get(formdef.id).internal_identifier == 'bar' |
123 | 123 | |
124 |
if not pub.is_using_postgresql(): |
|
125 |
# makes sure the internal_name doesn't change if there are submitted forms |
|
126 |
formdef.data_class()().store() |
|
127 |
formdef.name = 'baz' |
|
128 |
formdef.store() |
|
129 |
assert FormDef.get(formdef.id).name == 'baz' |
|
130 |
assert FormDef.get(formdef.id).internal_identifier == 'bar' # didn't change |
|
124 |
# makes sure the internal_name doesn't change if there are submitted forms |
|
125 |
formdef.data_class()().store() |
|
126 |
formdef.name = 'baz' |
|
127 |
formdef.store() |
|
128 |
assert FormDef.get(formdef.id).name == 'baz' |
|
129 |
assert FormDef.get(formdef.id).internal_identifier == 'bar' # didn't change |
|
131 | 130 | |
132 | 131 | |
133 | 132 |
def test_overlong_slug(pub): |
tests/test_sessions.py | ||
---|---|---|
224 | 224 | |
225 | 225 | |
226 | 226 |
def test_transient_data_removal(pub, app): |
227 |
if not pub.is_using_postgresql(): |
|
228 |
pytest.skip('this requires SQL') |
|
229 |
return |
|
230 | ||
231 | 227 |
pub.session_manager.session_class.wipe() |
232 | 228 |
sql.TransientData.wipe() |
233 | 229 |
resp = app.get('/') |
... | ... | |
251 | 247 | |
252 | 248 | |
253 | 249 |
def test_magictoken_migration(pub, app): |
254 |
if not pub.is_using_postgresql(): |
|
255 |
pytest.skip('this requires SQL') |
|
256 |
return |
|
257 | ||
258 | 250 |
pub.session_manager.session_class.wipe() |
259 | 251 |
sql.TransientData.wipe() |
260 | 252 |
resp = app.get('/') |
tests/utilities.py | ||
---|---|---|
85 | 85 |
pub.custom_view_class = sql.CustomView |
86 | 86 |
pub.snapshot_class = sql.Snapshot |
87 | 87 |
pub.loggederror_class = sql.LoggedError |
88 |
pub.is_using_postgresql = lambda: True |
|
89 | 88 |
else: |
90 | 89 |
pub.user_class = User |
91 | 90 |
pub.role_class = Role |
... | ... | |
93 | 92 |
pub.tracking_code_class = TrackingCode |
94 | 93 |
pub.session_class = sessions.BasicSession |
95 | 94 |
pub.custom_view_class = custom_views.CustomView |
96 |
pub.is_using_postgresql = lambda: False |
|
97 | 95 | |
98 | 96 |
pub.session_manager_class = sessions.StorageSessionManager |
99 | 97 |
pub.session_manager = pub.session_manager_class(session_class=pub.session_class) |
tests/workflow/test_all.py | ||
---|---|---|
373 | 373 | |
374 | 374 | |
375 | 375 |
def test_jump_bad_python_condition(two_pubs): |
376 |
if not two_pubs.is_using_postgresql(): |
|
377 |
pytest.skip('this requires SQL') |
|
378 |
return |
|
379 | ||
380 | 376 |
FormDef.wipe() |
381 | 377 |
formdef = FormDef() |
382 | 378 |
formdef.name = 'foobar' |
... | ... | |
433 | 429 |
item.condition = {'type': 'django', 'value': 'form_var_foo|first|upper == "X"'} |
434 | 430 |
assert item.check_condition(formdata) is False |
435 | 431 | |
436 |
if two_pubs.is_using_postgresql(): |
|
437 |
assert two_pubs.loggederror_class.count() == 0 |
|
432 |
assert two_pubs.loggederror_class.count() == 0 |
|
438 | 433 | |
439 | 434 |
item.condition = {'type': 'django', 'value': '~ invalid ~'} |
440 | 435 |
assert item.check_condition(formdata) is False |
441 |
if two_pubs.is_using_postgresql(): |
|
442 |
assert two_pubs.loggederror_class.count() == 1 |
|
443 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
444 |
assert logged_error.summary == 'Failed to evaluate condition' |
|
445 |
assert logged_error.exception_class == 'TemplateSyntaxError' |
|
446 |
assert logged_error.exception_message == "Could not parse the remainder: '~' from '~'" |
|
447 |
assert logged_error.expression == '~ invalid ~' |
|
448 |
assert logged_error.expression_type == 'django' |
|
436 |
assert two_pubs.loggederror_class.count() == 1 |
|
437 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
438 |
assert logged_error.summary == 'Failed to evaluate condition' |
|
439 |
assert logged_error.exception_class == 'TemplateSyntaxError' |
|
440 |
assert logged_error.exception_message == "Could not parse the remainder: '~' from '~'" |
|
441 |
assert logged_error.expression == '~ invalid ~' |
|
442 |
assert logged_error.expression_type == 'django' |
|
449 | 443 | |
450 | 444 | |
451 | 445 |
def test_check_auth(pub): |
... | ... | |
580 | 574 | |
581 | 575 | |
582 | 576 |
def test_dispatch_auto(two_pubs): |
583 |
if not two_pubs.is_using_postgresql(): |
|
584 |
pytest.skip('this requires sql') |
|
585 |
return |
|
586 | ||
587 | 577 |
formdef = FormDef() |
588 | 578 |
formdef.name = 'baz' |
589 | 579 |
formdef.fields = [ |
... | ... | |
671 | 661 | |
672 | 662 | |
673 | 663 |
def test_dispatch_computed(two_pubs): |
674 |
if not two_pubs.is_using_postgresql(): |
|
675 |
pytest.skip('this requires sql') |
|
676 |
return |
|
677 | ||
678 | 664 |
formdef = FormDef() |
679 | 665 |
formdef.name = 'baz' |
680 | 666 |
formdef.store() |
... | ... | |
1275 | 1261 |
two_pubs.substitutions.feed(formdata) |
1276 | 1262 |
item.perform(formdata) |
1277 | 1263 |
url1 = formdata.evolution[-1].parts[-1].content |
1278 |
if two_pubs.is_using_postgresql(): |
|
1279 |
assert two_pubs.loggederror_class.count() == 1 |
|
1280 |
error = two_pubs.loggederror_class.select()[0] |
|
1281 |
assert error.kind == 'deprecated_usage' |
|
1282 |
assert error.occurences_count == 1 |
|
1264 |
assert two_pubs.loggederror_class.count() == 1 |
|
1265 |
error = two_pubs.loggederror_class.select()[0] |
|
1266 |
assert error.kind == 'deprecated_usage' |
|
1267 |
assert error.occurences_count == 1 |
|
1283 | 1268 | |
1284 | 1269 |
two_pubs.substitutions.feed(formdata) |
1285 | 1270 |
item.comment = '{{ form_attachments.testfile.url }}' |
1286 | 1271 |
item.perform(formdata) |
1287 | 1272 |
url2 = formdata.evolution[-1].parts[-1].content |
1288 |
if two_pubs.is_using_postgresql(): |
|
1289 |
assert two_pubs.loggederror_class.count() == 1 |
|
1290 |
error = two_pubs.loggederror_class.select()[0] |
|
1291 |
assert error.kind == 'deprecated_usage' |
|
1292 |
assert error.occurences_count == 1 |
|
1273 |
assert two_pubs.loggederror_class.count() == 1 |
|
1274 |
error = two_pubs.loggederror_class.select()[0] |
|
1275 |
assert error.kind == 'deprecated_usage' |
|
1276 |
assert error.occurences_count == 1 |
|
1293 | 1277 | |
1294 | 1278 |
assert len(os.listdir(os.path.join(get_publisher().app_dir, 'attachments'))) == 1 |
1295 | 1279 |
for subdir in os.listdir(os.path.join(get_publisher().app_dir, 'attachments')): |
... | ... | |
1316 | 1300 |
item.comment = '[attachments.testfile.url]' |
1317 | 1301 |
item.perform(formdata) |
1318 | 1302 |
url3 = formdata.evolution[-1].parts[-1].content |
1319 |
if two_pubs.is_using_postgresql(): |
|
1320 |
assert two_pubs.loggederror_class.count() == 1 |
|
1321 |
error = two_pubs.loggederror_class.select()[0] |
|
1322 |
assert error.kind == 'deprecated_usage' |
|
1323 |
assert error.occurences_count == 2 |
|
1303 |
assert two_pubs.loggederror_class.count() == 1 |
|
1304 |
error = two_pubs.loggederror_class.select()[0] |
|
1305 |
assert error.kind == 'deprecated_usage' |
|
1306 |
assert error.occurences_count == 2 |
|
1324 | 1307 |
two_pubs.substitutions.feed(formdata) |
1325 | 1308 |
item.comment = '[form_attachments.testfile.url]' |
1326 | 1309 |
item.perform(formdata) |
1327 | 1310 |
url4 = formdata.evolution[-1].parts[-1].content |
1328 | 1311 |
assert url3 == url4 |
1329 |
if two_pubs.is_using_postgresql(): |
|
1330 |
assert two_pubs.loggederror_class.count() == 1 |
|
1331 |
error = two_pubs.loggederror_class.select()[0] |
|
1332 |
assert error.kind == 'deprecated_usage' |
|
1333 |
assert error.occurences_count == 2 |
|
1312 |
assert two_pubs.loggederror_class.count() == 1 |
|
1313 |
error = two_pubs.loggederror_class.select()[0] |
|
1314 |
assert error.kind == 'deprecated_usage' |
|
1315 |
assert error.occurences_count == 2 |
|
1334 | 1316 | |
1335 | 1317 | |
1336 | 1318 |
def test_register_comment_with_attachment_file(pub): |
... | ... | |
1808 | 1790 |
item.perform(formdata) |
1809 | 1791 |
assert formdata.status == 'wf-sterr' |
1810 | 1792 | |
1811 |
if pub.is_using_postgresql(): |
|
1812 |
pub.loggederror_class.wipe() |
|
1793 |
pub.loggederror_class.wipe() |
|
1813 | 1794 |
item.action_on_5xx = 'stdeleted' # removed status |
1814 | 1795 |
formdata.status = 'wf-st1' |
1815 | 1796 |
formdata.store() |
1816 | 1797 |
with pytest.raises(AbortActionException): |
1817 | 1798 |
item.perform(formdata) |
1818 | 1799 |
assert formdata.status == 'wf-st1' # unknown status acts like :stop |
1819 |
if pub.is_using_postgresql(): |
|
1820 |
assert pub.loggederror_class.count() == 1 |
|
1821 |
error = pub.loggederror_class.select()[0] |
|
1822 |
assert 'reference-to-invalid-status-stdeleted-in-workflow' in error.tech_id |
|
1823 |
assert error.occurences_count == 1 |
|
1800 |
assert pub.loggederror_class.count() == 1 |
|
1801 |
error = pub.loggederror_class.select()[0] |
|
1802 |
assert 'reference-to-invalid-status-stdeleted-in-workflow' in error.tech_id |
|
1803 |
assert error.occurences_count == 1 |
|
1824 | 1804 | |
1825 | 1805 |
item = WebserviceCallStatusItem() |
1826 | 1806 |
item.url = 'http://remote.example.net/xml' |
... | ... | |
2451 | 2431 | |
2452 | 2432 |
assert formdef.data_class().get(formdata_id).status == 'wf-st2' |
2453 | 2433 | |
2454 |
if two_pubs.is_using_postgresql(): |
|
2455 |
formdata = formdef.data_class()() |
|
2456 |
formdata.just_created() |
|
2434 |
formdata = formdef.data_class()() |
|
2435 |
formdata.just_created() |
|
2436 |
formdata.store() |
|
2437 |
formdata_id = formdata.id |
|
2438 |
with mock.patch('wcs.wf.jump.JumpWorkflowStatusItem.check_condition') as must_jump: |
|
2439 |
must_jump.return_value = False |
|
2440 |
_apply_timeouts(two_pubs) |
|
2441 |
assert must_jump.call_count == 0 # not enough time has passed |
|
2442 | ||
2443 |
# check a lower than minimal delay is not considered |
|
2444 |
jump.timeout = 5 * 50 # 5 minutes |
|
2445 |
workflow.store() |
|
2446 |
rewind(formdata, seconds=10 * 60) |
|
2447 |
formdata.store() |
|
2448 |
_apply_timeouts(two_pubs) |
|
2449 |
assert must_jump.call_count == 0 |
|
2450 | ||
2451 |
# but is executed once delay is reached |
|
2452 |
rewind(formdata, seconds=10 * 60) |
|
2457 | 2453 |
formdata.store() |
2458 |
formdata_id = formdata.id |
|
2459 |
with mock.patch('wcs.wf.jump.JumpWorkflowStatusItem.check_condition') as must_jump: |
|
2460 |
must_jump.return_value = False |
|
2461 |
_apply_timeouts(two_pubs) |
|
2462 |
assert must_jump.call_count == 0 # not enough time has passed |
|
2463 | ||
2464 |
# check a lower than minimal delay is not considered |
|
2465 |
jump.timeout = 5 * 50 # 5 minutes |
|
2466 |
workflow.store() |
|
2467 |
rewind(formdata, seconds=10 * 60) |
|
2468 |
formdata.store() |
|
2469 |
_apply_timeouts(two_pubs) |
|
2470 |
assert must_jump.call_count == 0 |
|
2471 | ||
2472 |
# but is executed once delay is reached |
|
2473 |
rewind(formdata, seconds=10 * 60) |
|
2474 |
formdata.store() |
|
2475 |
_apply_timeouts(two_pubs) |
|
2476 |
assert must_jump.call_count == 1 |
|
2477 | ||
2478 |
# check a templated timeout is considered as minimal delay for explicit evaluation |
|
2479 |
jump.timeout = '{{ "0" }}' |
|
2480 |
workflow.store() |
|
2481 |
_apply_timeouts(two_pubs) |
|
2482 |
assert must_jump.call_count == 2 |
|
2454 |
_apply_timeouts(two_pubs) |
|
2455 |
assert must_jump.call_count == 1 |
|
2456 | ||
2457 |
# check a templated timeout is considered as minimal delay for explicit evaluation |
|
2458 |
jump.timeout = '{{ "0" }}' |
|
2459 |
workflow.store() |
|
2460 |
_apply_timeouts(two_pubs) |
|
2461 |
assert must_jump.call_count == 2 |
|
2483 | 2462 | |
2484 | 2463 |
# check there's no crash on workflow without jumps |
2485 | 2464 |
formdef = FormDef() |
... | ... | |
2530 | 2509 |
formdata.store() |
2531 | 2510 |
formdata_id = formdata.id |
2532 | 2511 | |
2533 |
if two_pubs.is_using_postgresql(): |
|
2534 |
two_pubs.loggederror_class.wipe() |
|
2512 |
two_pubs.loggederror_class.wipe() |
|
2535 | 2513 | |
2536 | 2514 |
rewind(formdata, seconds=40 * 60) |
2537 | 2515 |
formdata.store() |
2538 | 2516 |
_apply_timeouts(two_pubs) |
2539 | 2517 |
assert formdef.data_class().get(formdata_id).status == 'wf-st1' # no change |
2540 | 2518 | |
2541 |
if two_pubs.is_using_postgresql(): |
|
2542 |
assert two_pubs.loggederror_class.count() == 1 |
|
2543 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
2544 |
assert logged_error.summary == "Error in timeout value '30 plop' (computed from '{{ 30 }} plop')" |
|
2519 |
assert two_pubs.loggederror_class.count() == 1 |
|
2520 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
2521 |
assert logged_error.summary == "Error in timeout value '30 plop' (computed from '{{ 30 }} plop')" |
|
2545 | 2522 | |
2546 | 2523 |
# template timeout value returning nothing |
2547 | 2524 |
jump.timeout = '{% if 1 %}{% endif %}' |
... | ... | |
2553 | 2530 |
formdata.store() |
2554 | 2531 |
formdata_id = formdata.id |
2555 | 2532 | |
2556 |
if two_pubs.is_using_postgresql(): |
|
2557 |
two_pubs.loggederror_class.wipe() |
|
2533 |
two_pubs.loggederror_class.wipe() |
|
2558 | 2534 | |
2559 | 2535 |
rewind(formdata, seconds=40 * 60) |
2560 | 2536 |
formdata.store() |
2561 | 2537 |
_apply_timeouts(two_pubs) |
2562 | 2538 |
assert formdef.data_class().get(formdata_id).status == 'wf-st1' # no change |
2563 | 2539 | |
2564 |
if two_pubs.is_using_postgresql(): |
|
2565 |
assert two_pubs.loggederror_class.count() == 1 |
|
2566 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
2567 |
assert logged_error.summary == "Error in timeout value '' (computed from '{% if 1 %}{% endif %}')" |
|
2540 |
assert two_pubs.loggederror_class.count() == 1 |
|
2541 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
2542 |
assert logged_error.summary == "Error in timeout value '' (computed from '{% if 1 %}{% endif %}')" |
|
2568 | 2543 | |
2569 | 2544 | |
2570 | 2545 |
def test_legacy_timeout(pub): |
... | ... | |
2663 | 2638 | |
2664 | 2639 | |
2665 | 2640 |
def test_jump_missing_previous_mark(two_pubs): |
2666 |
if not two_pubs.is_using_postgresql(): |
|
2667 |
pytest.skip('this requires SQL') |
|
2668 |
return |
|
2669 | ||
2670 | 2641 |
FormDef.wipe() |
2671 | 2642 |
Workflow.wipe() |
2672 | 2643 | |
... | ... | |
2847 | 2818 |
assert json_payload['to'] == ['1234'] |
2848 | 2819 |
assert json_payload['from'] == 'Passerelle' |
2849 | 2820 | |
2850 |
if pub.is_using_postgresql(): |
|
2851 |
pub.loggederror_class.wipe() |
|
2852 |
with mock.patch('wcs.wscalls.get_secret_and_orig') as mocked_secret_and_orig: |
|
2853 |
mocked_secret_and_orig.return_value = ('secret', 'localhost') |
|
2854 |
with mock.patch('wcs.qommon.misc._http_request') as mocked_http_post: |
|
2855 |
mocked_http_post.return_value = (mock.Mock(headers={}), 400, '{"err": 1}', 'headers') |
|
2856 |
item.perform(formdata) |
|
2857 |
assert pub.loggederror_class.count() == 1 |
|
2858 |
assert pub.loggederror_class.select()[0].summary == 'Could not send SMS' |
|
2821 |
pub.loggederror_class.wipe() |
|
2822 |
with mock.patch('wcs.wscalls.get_secret_and_orig') as mocked_secret_and_orig: |
|
2823 |
mocked_secret_and_orig.return_value = ('secret', 'localhost') |
|
2824 |
with mock.patch('wcs.qommon.misc._http_request') as mocked_http_post: |
|
2825 |
mocked_http_post.return_value = (mock.Mock(headers={}), 400, '{"err": 1}', 'headers') |
|
2826 |
item.perform(formdata) |
|
2827 |
assert pub.loggederror_class.count() == 1 |
|
2828 |
assert pub.loggederror_class.select()[0].summary == 'Could not send SMS' |
|
2859 | 2829 | |
2860 | 2830 | |
2861 | 2831 |
def test_display_form(two_pubs): |
... | ... | |
3340 | 3310 |
formdef.change_workflow(workflow) |
3341 | 3311 |
assert formdef.geolocations |
3342 | 3312 | |
3343 |
if two_pubs.is_using_postgresql(): |
|
3344 |
conn, cur = sql.get_connection_and_cursor() |
|
3345 |
assert column_exists_in_table(cur, formdef.table_name, 'geoloc_base') |
|
3346 |
conn.commit() |
|
3347 |
cur.close() |
|
3313 |
conn, cur = sql.get_connection_and_cursor() |
|
3314 |
assert column_exists_in_table(cur, formdef.table_name, 'geoloc_base') |
|
3315 |
conn.commit() |
|
3316 |
cur.close() |
|
3348 | 3317 | |
3349 | 3318 |
# change to current workflow |
3350 | 3319 |
workflow = Workflow(name='wf2') |
... | ... | |
3367 | 3336 |
formdef.refresh_from_storage() |
3368 | 3337 |
assert formdef.geolocations |
3369 | 3338 | |
3370 |
if two_pubs.is_using_postgresql(): |
|
3371 |
conn, cur = sql.get_connection_and_cursor() |
|
3372 |
assert column_exists_in_table(cur, formdef.table_name, 'geoloc_base') |
|
3373 |
conn.commit() |
|
3374 |
cur.close() |
|
3339 |
conn, cur = sql.get_connection_and_cursor() |
|
3340 |
assert column_exists_in_table(cur, formdef.table_name, 'geoloc_base') |
|
3341 |
conn.commit() |
|
3342 |
cur.close() |
|
3375 | 3343 | |
3376 | 3344 | |
3377 | 3345 |
def test_geolocate_address(two_pubs): |
... | ... | |
3450 | 3418 |
formdata.geolocations = None |
3451 | 3419 |
item.perform(formdata) |
3452 | 3420 |
assert formdata.geolocations == {} |
3453 |
if two_pubs.is_using_postgresql(): |
|
3454 |
assert two_pubs.loggederror_class.count() == 1 |
|
3455 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
3456 |
assert ( |
|
3457 |
logged_error.summary |
|
3458 |
== 'error in template for address string [syntax error in ezt template: unclosed block at line 1 and column 24]' |
|
3459 |
) |
|
3460 |
assert logged_error.formdata_id == str(formdata.id) |
|
3461 |
assert logged_error.exception_class == 'TemplateError' |
|
3462 |
assert ( |
|
3463 |
logged_error.exception_message |
|
3464 |
== 'syntax error in ezt template: unclosed block at line 1 and column 24' |
|
3465 |
) |
|
3466 |
two_pubs.loggederror_class.wipe() |
|
3421 |
assert two_pubs.loggederror_class.count() == 1 |
|
3422 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
3423 |
assert ( |
|
3424 |
logged_error.summary |
|
3425 |
== 'error in template for address string [syntax error in ezt template: unclosed block at line 1 and column 24]' |
|
3426 |
) |
|
3427 |
assert logged_error.formdata_id == str(formdata.id) |
|
3428 |
assert logged_error.exception_class == 'TemplateError' |
|
3429 |
assert ( |
|
3430 |
logged_error.exception_message |
|
3431 |
== 'syntax error in ezt template: unclosed block at line 1 and column 24' |
|
3432 |
) |
|
3433 |
two_pubs.loggederror_class.wipe() |
|
3467 | 3434 | |
3468 | 3435 |
# check for None |
3469 | 3436 |
item.address_string = '=None' |
... | ... | |
3492 | 3459 |
http_get_page.side_effect = ConnectionError('some error') |
3493 | 3460 |
item.perform(formdata) |
3494 | 3461 |
assert formdata.geolocations == {} |
3495 |
if two_pubs.is_using_postgresql(): |
|
3496 |
assert two_pubs.loggederror_class.count() == 1 |
|
3497 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
3498 |
assert logged_error.summary == 'error calling geocoding service [some error]' |
|
3499 |
assert logged_error.formdata_id == str(formdata.id) |
|
3500 |
assert logged_error.exception_class == 'ConnectionError' |
|
3501 |
assert logged_error.exception_message == 'some error' |
|
3462 |
assert two_pubs.loggederror_class.count() == 1 |
|
3463 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
3464 |
assert logged_error.summary == 'error calling geocoding service [some error]' |
|
3465 |
assert logged_error.formdata_id == str(formdata.id) |
|
3466 |
assert logged_error.exception_class == 'ConnectionError' |
|
3467 |
assert logged_error.exception_message == 'some error' |
|
3502 | 3468 | |
3503 | 3469 | |
3504 | 3470 |
def test_geolocate_image(pub): |
... | ... | |
3583 | 3549 |
formdata.geolocations = None |
3584 | 3550 |
formdata.data = {'2': '48.8337085'} |
3585 | 3551 |
item.map_variable = '=form_var_map' |
3586 |
if two_pubs.is_using_postgresql(): |
|
3587 |
assert two_pubs.loggederror_class.count() == 1 |
|
3588 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
3589 |
assert logged_error.summary == 'error geolocating from map variable' |
|
3590 |
assert logged_error.formdata_id == str(formdata.id) |
|
3591 |
assert logged_error.exception_class == 'ValueError' |
|
3592 |
assert logged_error.exception_message == 'not enough values to unpack (expected 2, got 1)' |
|
3552 |
assert two_pubs.loggederror_class.count() == 1 |
|
3553 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
3554 |
assert logged_error.summary == 'error geolocating from map variable' |
|
3555 |
assert logged_error.formdata_id == str(formdata.id) |
|
3556 |
assert logged_error.exception_class == 'ValueError' |
|
3557 |
assert logged_error.exception_message == 'not enough values to unpack (expected 2, got 1)' |
|
3593 | 3558 | |
3594 | 3559 | |
3595 | 3560 |
def test_geolocate_overwrite(pub): |
... | ... | |
4581 | 4546 |
formdata = formdef.data_class().get(formdata.id) |
4582 | 4547 |
assert formdata.data['bo1'] == '' |
4583 | 4548 | |
4584 |
if two_pubs.is_using_postgresql(): |
|
4585 |
assert two_pubs.loggederror_class.count() == 0 |
|
4549 |
assert two_pubs.loggederror_class.count() == 0 |
|
4586 | 4550 | |
4587 | 4551 |
item.fields = [{'field_id': 'bo1', 'value': '= ~ invalid python ~'}] |
4588 | 4552 |
item.perform(formdata) |
4589 | 4553 |
formdata = formdef.data_class().get(formdata.id) |
4590 |
if two_pubs.is_using_postgresql(): |
|
4591 |
assert two_pubs.loggederror_class.count() == 1 |
|
4592 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4593 |
assert logged_error.summary == 'Failed to compute Python expression' |
|
4594 |
assert logged_error.formdata_id == str(formdata.id) |
|
4595 |
assert logged_error.expression == ' ~ invalid python ~' |
|
4596 |
assert logged_error.expression_type == 'python' |
|
4597 |
assert logged_error.exception_class == 'SyntaxError' |
|
4598 |
assert logged_error.exception_message == 'invalid syntax (<string>, line 1)' |
|
4554 |
assert two_pubs.loggederror_class.count() == 1 |
|
4555 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4556 |
assert logged_error.summary == 'Failed to compute Python expression' |
|
4557 |
assert logged_error.formdata_id == str(formdata.id) |
|
4558 |
assert logged_error.expression == ' ~ invalid python ~' |
|
4559 |
assert logged_error.expression_type == 'python' |
|
4560 |
assert logged_error.exception_class == 'SyntaxError' |
|
4561 |
assert logged_error.exception_message == 'invalid syntax (<string>, line 1)' |
|
4599 | 4562 | |
4600 |
if two_pubs.is_using_postgresql(): |
|
4601 |
two_pubs.loggederror_class.wipe() |
|
4563 |
two_pubs.loggederror_class.wipe() |
|
4602 | 4564 |
item.fields = [{'field_id': 'bo1', 'value': '{% if bad django %}'}] |
4603 | 4565 |
item.perform(formdata) |
4604 | 4566 |
formdata = formdef.data_class().get(formdata.id) |
4605 |
if two_pubs.is_using_postgresql(): |
|
4606 |
assert two_pubs.loggederror_class.count() == 1 |
|
4607 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4608 |
assert logged_error.summary == 'Failed to compute template' |
|
4609 |
assert logged_error.formdata_id == str(formdata.id) |
|
4610 |
assert logged_error.expression == '{% if bad django %}' |
|
4611 |
assert logged_error.expression_type == 'template' |
|
4612 |
assert logged_error.exception_class == 'TemplateError' |
|
4613 |
assert logged_error.exception_message.startswith('syntax error in Django template') |
|
4567 |
assert two_pubs.loggederror_class.count() == 1 |
|
4568 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4569 |
assert logged_error.summary == 'Failed to compute template' |
|
4570 |
assert logged_error.formdata_id == str(formdata.id) |
|
4571 |
assert logged_error.expression == '{% if bad django %}' |
|
4572 |
assert logged_error.expression_type == 'template' |
|
4573 |
assert logged_error.exception_class == 'TemplateError' |
|
4574 |
assert logged_error.exception_message.startswith('syntax error in Django template') |
|
4614 | 4575 | |
4615 | 4576 | |
4616 | 4577 |
def test_set_backoffice_field_map(http_requests, two_pubs): |
... | ... | |
4652 | 4613 |
formdata = formdef.data_class().get(formdata.id) |
4653 | 4614 |
assert formdata.data.get('bo1') is None |
4654 | 4615 | |
4655 |
if two_pubs.is_using_postgresql(): |
|
4656 |
assert two_pubs.loggederror_class.count() == 0 |
|
4616 |
assert two_pubs.loggederror_class.count() == 0 |
|
4657 | 4617 | |
4658 | 4618 |
item.fields = [{'field_id': 'bo1', 'value': 'invalid value'}] |
4659 | 4619 |
item.perform(formdata) |
4660 | 4620 |
formdata = formdef.data_class().get(formdata.id) |
4661 |
if two_pubs.is_using_postgresql(): |
|
4662 |
assert two_pubs.loggederror_class.count() == 1 |
|
4663 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4664 |
assert ( |
|
4665 |
logged_error.summary |
|
4666 |
== "Failed to set Map field (bo1), error: invalid coordinates 'invalid value' (missing ;)" |
|
4667 |
) |
|
4668 |
assert logged_error.formdata_id == str(formdata.id) |
|
4669 |
assert logged_error.exception_class == 'SetValueError' |
|
4670 |
assert logged_error.exception_message == "invalid coordinates 'invalid value' (missing ;)" |
|
4671 |
two_pubs.loggederror_class.wipe() |
|
4621 |
assert two_pubs.loggederror_class.count() == 1 |
|
4622 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4623 |
assert ( |
|
4624 |
logged_error.summary |
|
4625 |
== "Failed to set Map field (bo1), error: invalid coordinates 'invalid value' (missing ;)" |
|
4626 |
) |
|
4627 |
assert logged_error.formdata_id == str(formdata.id) |
|
4628 |
assert logged_error.exception_class == 'SetValueError' |
|
4629 |
assert logged_error.exception_message == "invalid coordinates 'invalid value' (missing ;)" |
|
4630 |
two_pubs.loggederror_class.wipe() |
|
4672 | 4631 | |
4673 | 4632 |
item.fields = [{'field_id': 'bo1', 'value': 'XXX;YYY'}] |
4674 | 4633 |
item.perform(formdata) |
4675 | 4634 |
formdata = formdef.data_class().get(formdata.id) |
4676 |
if two_pubs.is_using_postgresql(): |
|
4677 |
assert two_pubs.loggederror_class.count() == 1 |
|
4678 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4679 |
assert logged_error.summary == "Failed to set Map field (bo1), error: invalid coordinates 'XXX;YYY'" |
|
4680 |
assert logged_error.formdata_id == str(formdata.id) |
|
4681 |
assert logged_error.exception_class == 'SetValueError' |
|
4682 |
assert logged_error.exception_message == "invalid coordinates 'XXX;YYY'" |
|
4683 |
two_pubs.loggederror_class.wipe() |
|
4635 |
assert two_pubs.loggederror_class.count() == 1 |
|
4636 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4637 |
assert logged_error.summary == "Failed to set Map field (bo1), error: invalid coordinates 'XXX;YYY'" |
|
4638 |
assert logged_error.formdata_id == str(formdata.id) |
|
4639 |
assert logged_error.exception_class == 'SetValueError' |
|
4640 |
assert logged_error.exception_message == "invalid coordinates 'XXX;YYY'" |
|
4641 |
two_pubs.loggederror_class.wipe() |
|
4684 | 4642 | |
4685 | 4643 | |
4686 | 4644 |
def test_set_backoffice_field_decimal(http_requests, two_pubs): |
... | ... | |
4977 | 4935 |
item.parent = st1 |
4978 | 4936 |
item.fields = [{'field_id': 'bo1', 'value': value}] |
4979 | 4937 | |
4980 |
if two_pubs.is_using_postgresql(): |
|
4981 |
two_pubs.loggederror_class.wipe() |
|
4938 |
two_pubs.loggederror_class.wipe() |
|
4982 | 4939 |
item.perform(formdata) |
4983 | 4940 | |
4984 | 4941 |
formdata = formdef.data_class().get(formdata.id) |
4985 | 4942 |
assert formdata.data['bo1'].base_filename == 'hello.txt' |
4986 | 4943 |
assert formdata.data['bo1'].get_content() == b'HELLO WORLD' |
4987 |
if two_pubs.is_using_postgresql(): |
|
4988 |
assert two_pubs.loggederror_class.count() == 1 |
|
4989 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4990 |
assert logged_error.summary.startswith('Failed to convert') |
|
4991 |
assert logged_error.formdata_id == str(formdata.id) |
|
4992 |
assert logged_error.exception_class == 'ValueError' |
|
4944 |
assert two_pubs.loggederror_class.count() == 1 |
|
4945 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
4946 |
assert logged_error.summary.startswith('Failed to convert') |
|
4947 |
assert logged_error.formdata_id == str(formdata.id) |
|
4948 |
assert logged_error.exception_class == 'ValueError' |
|
4993 | 4949 | |
4994 | 4950 |
# check wrong field |
4995 | 4951 |
item = SetBackofficeFieldsWorkflowStatusItem() |
... | ... | |
5207 | 5163 |
assert formdata.data['bo1_structured']['attr'] == 'attr1' |
5208 | 5164 | |
5209 | 5165 |
# reset, with unknown value |
5210 |
if two_pubs.is_using_postgresql(): |
|
5211 |
two_pubs.loggederror_class.wipe() |
|
5166 |
two_pubs.loggederror_class.wipe() |
|
5212 | 5167 |
formdata.data = {} |
5213 | 5168 |
formdata.store() |
5214 | 5169 |
item.fields = [{'field_id': 'bo1', 'value': 'xxx'}] |
... | ... | |
5217 | 5172 |
assert formdata.data.get('bo1') is None # invalid value is not stored |
5218 | 5173 |
assert formdata.data.get('bo1_display') is None |
5219 | 5174 |
assert formdata.data.get('bo1_structured') is None |
5220 |
if two_pubs.is_using_postgresql(): |
|
5221 |
assert two_pubs.loggederror_class.count() == 1 |
|
5222 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
5223 |
assert logged_error.summary.startswith('Failed to convert') |
|
5175 |
assert two_pubs.loggederror_class.count() == 1 |
|
5176 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
5177 |
assert logged_error.summary.startswith('Failed to convert') |
|
5224 | 5178 | |
5225 | 5179 |
# reset, and get empty value |
5226 | 5180 |
formdata.data = {} |
... | ... | |
5398 | 5352 |
assert len(formdata.data['bo1_structured']) == 1 |
5399 | 5353 | |
5400 | 5354 |
# using an invalid value |
5401 |
if two_pubs.is_using_postgresql(): |
|
5402 |
formdata.data = {} |
|
5403 |
formdata.store() |
|
5404 |
two_pubs.loggederror_class.wipe() |
|
5405 |
item = SetBackofficeFieldsWorkflowStatusItem() |
|
5406 |
item.parent = st1 |
|
5407 |
item.fields = [{'field_id': 'bo1', 'value': "=Ellipsis"}] |
|
5408 |
item.perform(formdata) |
|
5409 |
assert two_pubs.loggederror_class.count() == 1 |
|
5410 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
5411 |
assert 'Failed to convert' in logged_error.summary |
|
5355 |
formdata.data = {} |
|
5356 |
formdata.store() |
|
5357 |
two_pubs.loggederror_class.wipe() |
|
5358 |
item = SetBackofficeFieldsWorkflowStatusItem() |
|
5359 |
item.parent = st1 |
|
5360 |
item.fields = [{'field_id': 'bo1', 'value': "=Ellipsis"}] |
|
5361 |
item.perform(formdata) |
|
5362 |
assert two_pubs.loggederror_class.count() == 1 |
|
5363 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
5364 |
assert 'Failed to convert' in logged_error.summary |
|
5412 | 5365 | |
5413 | 5366 |
# using a string with multiple values |
5414 | 5367 |
item = SetBackofficeFieldsWorkflowStatusItem() |
... | ... | |
5473 | 5426 |
assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23) |
5474 | 5427 | |
5475 | 5428 |
# invalid values => do nothing |
5476 |
if two_pubs.is_using_postgresql(): |
|
5477 |
assert two_pubs.loggederror_class.count() == 0 |
|
5429 |
assert two_pubs.loggederror_class.count() == 0 |
|
5478 | 5430 |
for value in ('plop', '={}', '=[]'): |
5479 | 5431 |
item = SetBackofficeFieldsWorkflowStatusItem() |
5480 | 5432 |
item.parent = st1 |
5481 | 5433 |
item.fields = [{'field_id': 'bo1', 'value': value}] |
5482 | 5434 | |
5483 |
if two_pubs.is_using_postgresql(): |
|
5484 |
two_pubs.loggederror_class.wipe() |
|
5435 |
two_pubs.loggederror_class.wipe() |
|
5485 | 5436 |
item.perform(formdata) |
5486 | 5437 |
formdata = formdef.data_class().get(formdata.id) |
5487 | 5438 |
assert datetime.date(*formdata.data['bo1'][:3]) == datetime.date(2017, 3, 23) |
5488 |
if two_pubs.is_using_postgresql(): |
|
5489 |
assert two_pubs.loggederror_class.count() == 1 |
|
5490 |
assert two_pubs.loggederror_class.select()[0].summary.startswith('Failed to convert') |
|
5439 |
assert two_pubs.loggederror_class.count() == 1 |
|
5440 |
assert two_pubs.loggederror_class.select()[0].summary.startswith('Failed to convert') |
|
5491 | 5441 | |
5492 | 5442 |
# None : empty date |
5493 | 5443 |
item = SetBackofficeFieldsWorkflowStatusItem() |
... | ... | |
5986 | 5936 |
assert len(FormDef.get(formdef.id).data_class().get_actionable_ids([role.id])) == 2 |
5987 | 5937 | |
5988 | 5938 |
# bad condition |
5989 |
if two_pubs.is_using_postgresql(): |
|
5990 |
two_pubs.loggederror_class.wipe() |
|
5939 |
two_pubs.loggederror_class.wipe() |
|
5991 | 5940 |
choice.condition = {'type': 'python', 'value': 'foobar == barfoo'} |
5992 | 5941 |
workflow.store() |
5993 | 5942 |
assert len(FormDef.get(formdef.id).data_class().get_actionable_ids([role.id])) == 0 |
5994 |
if two_pubs.is_using_postgresql(): |
|
5995 |
assert two_pubs.loggederror_class.count() == 1 |
|
5996 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
5997 |
assert logged_error.occurences_count > 1 # should be 2... == 12 with pickle, 4 with sql |
|
5998 |
assert logged_error.summary == 'Failed to evaluate condition' |
|
5999 |
assert logged_error.exception_class == 'NameError' |
|
6000 |
assert logged_error.exception_message == "name 'foobar' is not defined" |
|
6001 |
assert logged_error.expression == 'foobar == barfoo' |
|
6002 |
assert logged_error.expression_type == 'python' |
|
5943 |
assert two_pubs.loggederror_class.count() == 1 |
|
5944 |
logged_error = two_pubs.loggederror_class.select()[0] |
|
5945 |
assert logged_error.occurences_count > 1 # should be 2... == 12 with pickle, 4 with sql |
|
5946 |
assert logged_error.summary == 'Failed to evaluate condition' |
|
5947 |
assert logged_error.exception_class == 'NameError' |
|
5948 |
assert logged_error.exception_message == "name 'foobar' is not defined" |
|
5949 |
assert logged_error.expression == 'foobar == barfoo' |
|
5950 |
assert logged_error.expression_type == 'python' |
|
6003 | 5951 | |
6004 | 5952 | |
6005 | 5953 |
def test_workflow_field_migration(pub): |
... | ... | |
6517 | 6465 | |
6518 | 6466 | |
6519 | 6467 |
def test_call_external_workflow_manual_targeting(two_pubs): |
6520 |
if not two_pubs.is_using_postgresql(): |
|
6521 |
pytest.skip('this requires SQL') |
|
6522 |
return |
|
6523 | ||
6524 | 6468 |
FormDef.wipe() |
6525 | 6469 |
CardDef.wipe() |
6526 | 6470 | |
... | ... | |
6701 | 6645 | |
6702 | 6646 | |
6703 | 6647 |
def test_call_external_workflow_manual_queryset_targeting(two_pubs): |
6704 |
if not two_pubs.is_using_postgresql(): |
|
6705 |
pytest.skip('this requires SQL') |
|
6706 |
return |
|
6707 | ||
6708 | 6648 |
FormDef.wipe() |
6709 | 6649 |
CardDef.wipe() |
6710 | 6650 |
tests/workflow/test_carddata.py | ||
---|---|---|
104 | 104 | |
105 | 105 |
assert carddef.data_class().count() == 1 |
106 | 106 | |
107 |
if two_pubs.is_using_postgresql(): |
|
108 |
errors = two_pubs.loggederror_class.select() |
|
109 |
assert len(errors) == 2 |
|
110 |
assert any('form_var_undefined' in (error.exception_message or '') for error in errors) |
|
111 |
assert any('invalid date value' in (error.exception_message or '') for error in errors) |
|
107 |
errors = two_pubs.loggederror_class.select() |
|
108 |
assert len(errors) == 2 |
|
109 |
assert any('form_var_undefined' in (error.exception_message or '') for error in errors) |
|
110 |
assert any('invalid date value' in (error.exception_message or '') for error in errors) |
|
112 | 111 | |
113 | 112 |
formdata = formdef.data_class()() |
114 | 113 |
today = datetime.date.today() |
... | ... | |
384 | 383 |
assert carddef.data_class().count() == 1 |
385 | 384 |
assert not carddef.data_class().select()[0].data.get('1') |
386 | 385 | |
387 |
if two_pubs.is_using_postgresql(): |
|
388 |
errors = two_pubs.loggederror_class.select() |
|
389 |
assert len(errors) == 1 |
|
390 |
assert any('invalid coordinates' in (error.exception_message or '') for error in errors) |
|
386 |
errors = two_pubs.loggederror_class.select() |
|
387 |
assert len(errors) == 1 |
|
388 |
assert any('invalid coordinates' in (error.exception_message or '') for error in errors) |
|
391 | 389 | |
392 | 390 |
# value from formdata |
393 | 391 |
create.mappings[0].expression = '{{ form_var_map }}' |
... | ... | |
742 | 740 | |
743 | 741 | |
744 | 742 |
def test_edit_carddata_manual_targeting(two_pubs): |
745 |
if not two_pubs.is_using_postgresql(): |
|
746 |
pytest.skip('this requires SQL') |
|
747 |
return |
|
748 | ||
749 | 743 |
FormDef.wipe() |
750 | 744 |
CardDef.wipe() |
751 | 745 | |
... | ... | |
1142 | 1136 | |
1143 | 1137 | |
1144 | 1138 |
def test_assign_carddata_manual_targeting(two_pubs): |
1145 |
if not two_pubs.is_using_postgresql(): |
|
1146 |
pytest.skip('this requires SQL') |
|
1147 |
return |
|
1148 | ||
1149 | 1139 |
FormDef.wipe() |
1150 | 1140 |
CardDef.wipe() |
1151 | 1141 |
two_pubs.user_class.wipe() |
tests/workflow/test_formdata.py | ||
---|---|---|
82 | 82 |
formdata.just_created() |
83 | 83 | |
84 | 84 |
assert target_formdef.data_class().count() == 0 |
85 |
if two_pubs.is_using_postgresql(): |
|
86 |
assert two_pubs.loggederror_class.count() == 0 |
|
85 |
assert two_pubs.loggederror_class.count() == 0 |
|
87 | 86 |
# check unconfigure action do nothing |
88 | 87 |
formdata.perform_workflow() |
89 | 88 |
assert target_formdef.data_class().count() == 0 |
... | ... | |
94 | 93 |
formdata.perform_workflow() |
95 | 94 |
assert target_formdef.data_class().count() == 1 |
96 | 95 | |
97 |
if two_pubs.is_using_postgresql(): |
|
98 |
errors = two_pubs.loggederror_class.select() |
|
99 |
assert len(errors) == 2 |
|
100 |
assert 'form_var_toto_string' in errors[0].exception_message |
|
101 |
assert errors[1].summary == 'Missing field: unknown (1), unknown (2)' |
|
102 |
assert errors[0].formdata_id == str(target_formdef.data_class().select()[0].id) |
|
103 |
assert errors[1].formdata_id == str(target_formdef.data_class().select()[0].id) |
|
104 | ||
105 |
if two_pubs.is_using_postgresql(): |
|
106 |
# add field labels cache |
|
107 |
two_pubs.loggederror_class.wipe() |
|
108 |
target_formdef.data_class().wipe() |
|
109 |
create.formdef_slug = target_formdef.url_name |
|
110 |
create.cached_field_labels = {'0': 'field0', '1': 'field1', '2': 'field2'} |
|
111 |
wf.store() |
|
112 |
del source_formdef._workflow |
|
113 |
formdata.perform_workflow() |
|
114 |
assert target_formdef.data_class().count() == 1 |
|
115 | ||
116 |
errors = two_pubs.loggederror_class.select() |
|
117 |
assert len(errors) == 2 |
|
118 |
assert errors[1].summary == 'Missing field: field1, field2' |
|
96 |
errors = two_pubs.loggederror_class.select() |
|
97 |
assert len(errors) == 2 |
|
98 |
assert 'form_var_toto_string' in errors[0].exception_message |
|
99 |
assert errors[1].summary == 'Missing field: unknown (1), unknown (2)' |
|
100 |
assert errors[0].formdata_id == str(target_formdef.data_class().select()[0].id) |
|
101 |
assert errors[1].formdata_id == str(target_formdef.data_class().select()[0].id) |
|
102 | ||
103 |
# add field labels cache |
|
104 |
two_pubs.loggederror_class.wipe() |
|
105 |
target_formdef.data_class().wipe() |
|
106 |
create.formdef_slug = target_formdef.url_name |
|
107 |
create.cached_field_labels = {'0': 'field0', '1': 'field1', '2': 'field2'} |
|
108 |
wf.store() |
|
109 |
del source_formdef._workflow |
|
110 |
formdata.perform_workflow() |
|
111 |
assert target_formdef.data_class().count() == 1 |
|
112 | ||
113 |
errors = two_pubs.loggederror_class.select() |
|
114 |
assert len(errors) == 2 |
|
115 |
assert errors[1].summary == 'Missing field: field1, field2' |
|
119 | 116 | |
120 | 117 |
# no tracking code has been created |
121 | 118 |
created_formdata = target_formdef.data_class().select()[0] |
... | ... | |
274 | 271 | |
275 | 272 | |
276 | 273 |
def test_create_formdata_card_item_mapping(two_pubs): |
277 |
if two_pubs.is_using_postgresql(): |
|
278 |
two_pubs.loggederror_class.wipe() |
|
274 |
two_pubs.loggederror_class.wipe() |
|
279 | 275 |
FormDef.wipe() |
280 | 276 |
CardDef.wipe() |
281 | 277 | |
... | ... | |
367 | 363 |
target_formdata = target_formdef.data_class().select()[0] |
368 | 364 |
assert target_formdata.data.get('0') is None |
369 | 365 |
assert target_formdata.data.get('0_display') is None |
370 |
if two_pubs.is_using_postgresql(): |
|
371 |
assert two_pubs.loggederror_class.count() == 1 |
|
372 |
assert two_pubs.loggederror_class.count() == 1 |
|
373 |
error = two_pubs.loggederror_class.select()[0] |
|
374 |
assert error.exception_message == "unknown card value ('XXX')" |
|
366 |
assert two_pubs.loggederror_class.count() == 1 |
|
367 |
assert two_pubs.loggederror_class.count() == 1 |
|
368 |
error = two_pubs.loggederror_class.select()[0] |
|
369 |
assert error.exception_message == "unknown card value ('XXX')" |
wcs/admin/data_sources.py | ||
---|---|---|
539 | 539 |
'categories': categories, |
540 | 540 |
'user_data_sources': user_data_sources, |
541 | 541 |
'has_chrono': has_chrono(get_publisher()), |
542 |
'has_users': get_publisher().is_using_postgresql(),
|
|
542 |
'has_users': True,
|
|
543 | 543 |
'agenda_data_sources': agenda_data_sources, |
544 | 544 |
'generated_data_sources': generated_data_sources, |
545 | 545 |
}, |
wcs/admin/forms.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
import difflib |
18 | 18 |
import io |
19 |
import tarfile |
|
20 |
import time |
|
21 | 19 |
import xml.etree.ElementTree as ET |
22 | 20 |
from collections import defaultdict |
23 | 21 | |
... | ... | |
604 | 602 |
'duplicate', |
605 | 603 |
'export', |
606 | 604 |
'anonymise', |
607 |
'archive', |
|
608 | 605 |
'enable', |
609 | 606 |
'workflow', |
610 | 607 |
'role', |
... | ... | |
932 | 929 |
r += htmltext('<li><a rel="popup" href="history/save">%s</a></li>') % _('Save snapshot') |
933 | 930 |
r += htmltext('<li><a href="history/">%s</a></li>') % _('History') |
934 | 931 |
r += htmltext('<li><a href="inspect">%s</a></li>') % _('Inspector') |
935 |
if not get_publisher().is_using_postgresql() and self.formdef_class == FormDef: |
|
936 |
r += htmltext('<li><a href="archive">%s</a></li>') % _('Archive') |
|
937 | 932 |
r += htmltext('</ul>') |
938 | 933 | |
939 | 934 |
r += htmltext('<ul>') |
... | ... | |
1276 | 1271 |
return redirect('../%s/' % self.formdefui.formdef.id) |
1277 | 1272 | |
1278 | 1273 |
def get_check_deletion_message(self): |
1279 |
if not get_publisher().is_using_postgresql(): |
|
1280 |
return None |
|
1281 | 1274 |
from wcs import sql |
1282 | 1275 | |
1283 | 1276 |
criterias = [ |
... | ... | |
1570 | 1563 |
content_type='application/x-wcs-form', |
1571 | 1564 |
) |
1572 | 1565 | |
1573 |
def archive(self): |
|
1574 |
if get_publisher().is_using_postgresql(): |
|
1575 |
raise TraversalError() |
|
1576 | ||
1577 |
if get_request().form.get('download'): |
|
1578 |
return self.archive_download() |
|
1579 | ||
1580 |
form = Form(enctype='multipart/form-data') |
|
1581 | ||
1582 |
form.add(DateWidget, 'date', title=_('Archive forms handled before')) |
|
1583 |
form.add(CheckboxWidget, 'not-done', title=_('Include forms that have not been handled'), value=False) |
|
1584 |
form.add(CheckboxWidget, 'keep', title=_('Do not remove forms'), value=False) |
|
1585 |
form.add_submit('submit', _('Submit')) |
|
1586 |
form.add_submit('cancel', _('Cancel')) |
|
1587 | ||
1588 |
if form.get_widget('cancel').parse(): |
|
1589 |
return redirect('.') |
|
1590 | ||
1591 |
if not form.is_submitted() or form.has_errors(): |
|
1592 |
get_response().breadcrumb.append(('archive', _('Archive'))) |
|
1593 |
self.html_top(title=_('Archive Forms')) |
|
1594 |
r = TemplateIO(html=True) |
|
1595 |
r += htmltext('<h2>%s</h2>') % _('Archive Forms') |
|
1596 |
r += form.render() |
|
1597 |
return r.getvalue() |
|
1598 |
else: |
|
1599 |
return self.archive_submit(form) |
|
1600 | ||
1601 |
def archive_submit(self, form): |
|
1602 |
class Archiver: |
|
1603 |
def __init__(self, formdef): |
|
1604 |
self.formdef = formdef |
|
1605 | ||
1606 |
def archive(self, job=None): |
|
1607 |
all_forms = self.formdef.data_class().select() |
|
1608 | ||
1609 |
if form.get_widget('not-done').parse() is False: |
|
1610 |
not_endpoint_status = self.formdef.workflow.get_not_endpoint_status() |
|
1611 |
not_endpoint_status_ids = ['wf-%s' % x.id for x in not_endpoint_status] |
|
1612 |
all_forms = [x for x in all_forms if x.status not in not_endpoint_status_ids] |
|
1613 | ||
1614 |
if form.get_widget('date').parse(): |
|
1615 |
date = form.get_widget('date').parse() |
|
1616 |
date = time.strptime(date, misc.date_format()) |
|
1617 |
all_forms = [x for x in all_forms if x.last_update_time < date] |
|
1618 | ||
1619 |
self.fd = io.BytesIO() |
|
1620 |
with tarfile.open('wcs.tar.gz', 'w:gz', fileobj=self.fd) as t: |
|
1621 |
t.add(self.formdef.get_object_filename(), 'formdef') |
|
1622 |
for formdata in all_forms: |
|
1623 |
t.add( |
|
1624 |
formdata.get_object_filename(), |
|
1625 |
'%s/%s' % (self.formdef.url_name, str(formdata.id)), |
|
1626 |
) |
|
1627 | ||
1628 |
if form.get_widget('keep').parse() is False: |
|
1629 |
for f in all_forms: |
|
1630 |
f.remove_self() |
|
1631 | ||
1632 |
if job: |
|
1633 |
job.file_content = self.fd.getvalue() |
|
1634 |
job.store() |
|
1635 | ||
1636 |
count = self.formdef.data_class().count() |
|
1637 |
archiver = Archiver(self.formdef) |
|
1638 |
if count > 100: # Arbitrary threshold |
|
1639 |
job = get_response().add_after_job( |
|
1640 |
_('Archiving forms'), |
|
1641 |
archiver.archive, |
|
1642 |
done_action_url=self.formdef.get_admin_url() + 'archive?job=%(job_id)s', |
|
1643 |
done_action_label=_('Download Archive'), |
|
1644 |
) |
|
1645 |
job.store() |
|
1646 |
return redirect(job.get_processing_url()) |
|
1647 |
else: |
|
1648 |
archiver.archive() |
|
1649 | ||
1650 |
response = get_response() |
|
1651 |
response.set_content_type('application/x-wcs-archive') |
|
1652 |
response.set_header( |
|
1653 |
'content-disposition', 'attachment; filename=%s-archive.wcs' % self.formdef.url_name |
|
1654 |
) |
|
1655 |
return archiver.fd.getvalue() |
|
1656 | ||
1657 |
def archive_download(self): |
|
1658 |
try: |
|
1659 |
job = AfterJob.get(get_request().form.get('download')) |
|
1660 |
except KeyError: |
|
1661 |
return redirect('.') |
|
1662 | ||
1663 |
if not job.status == 'completed': |
|
1664 |
raise TraversalError() |
|
1665 |
response = get_response() |
|
1666 |
response.set_content_type('application/x-wcs-archive') |
|
1667 |
response.set_header( |
|
1668 |
'content-disposition', 'attachment; filename=%s-archive.wcs' % self.formdef.url_name |
|
1669 |
) |
|
1670 |
return job.file_content |
|
1671 | ||
1672 | 1566 |
def enable(self): |
1673 | 1567 |
self.formdef.disabled = False |
1674 | 1568 |
self.formdef.store(comment=_('Enable')) |
wcs/admin/logged_errors.py | ||
---|---|---|
221 | 221 |
workflow_id=self.workflow_id, |
222 | 222 |
) |
223 | 223 |
links = '' |
224 |
if get_publisher().is_using_postgresql(): |
|
225 |
links = pagination_links(offset, limit, total_count, load_js=False) |
|
224 |
links = pagination_links(offset, limit, total_count, load_js=False) |
|
226 | 225 |
return template.QommonTemplateResponse( |
227 | 226 |
templates=['wcs/backoffice/logged-errors.html'], |
228 | 227 |
context={ |
wcs/admin/settings.py | ||
---|---|---|
300 | 300 |
self.publisher.cfg['users'] = users_cfg |
301 | 301 |
self.publisher.write_cfg() |
302 | 302 |
self.publisher._cached_user_fields_formdef = None |
303 |
if self.publisher.is_using_postgresql(): |
|
304 |
from wcs import sql |
|
303 |
from wcs import sql |
|
305 | 304 | |
306 |
sql.do_user_table()
|
|
305 |
sql.do_user_table() |
|
307 | 306 | |
308 | 307 | |
309 | 308 |
class UsersDirectory(Directory): |
wcs/api.py | ||
---|---|---|
422 | 422 |
raise AccessForbiddenError('user not allowed to ignore roles') |
423 | 423 | |
424 | 424 |
def _q_index(self): |
425 |
if not get_publisher().is_using_postgresql(): |
|
426 |
raise TraversalError() |
|
427 | ||
428 | 425 |
self.check_access() |
429 | 426 |
get_request()._user = get_user_from_api_query_string() or get_request().user |
430 | 427 | |
... | ... | |
491 | 488 |
return json.dumps({'data': output}, cls=misc.JSONEncoder) |
492 | 489 | |
493 | 490 |
def geojson(self): |
494 |
if not get_publisher().is_using_postgresql(): |
|
495 |
raise TraversalError() |
|
496 | 491 |
self.check_access() |
497 | 492 |
get_request()._user = get_user_from_api_query_string() or get_request().user |
498 | 493 |
return ManagementDirectory().geojson() |
... | ... | |
743 | 738 |
if include_count: |
744 | 739 |
# we include the count of submitted forms so it's possible to sort |
745 | 740 |
# them by "popularity" |
746 |
if get_publisher().is_using_postgresql(): |
|
747 |
from wcs import sql |
|
748 | ||
749 |
# 4 * number of submitted forms of last 2 days |
|
750 |
# + 2 * number of submitted forms of last 8 days |
|
751 |
# + 1 * number of submitted forms of last 30 days |
|
752 |
# exclude drafts |
|
753 |
criterias = [Equal('formdef_id', formdef.id), StrictNotEqual('status', 'draft')] |
|
754 |
d_now = datetime.datetime.now() |
|
755 |
count = 4 * sql.get_period_total( |
|
756 |
period_start=d_now - datetime.timedelta(days=2), |
|
757 |
include_start=True, |
|
758 |
criterias=criterias, |
|
759 |
) |
|
760 |
count += 2 * sql.get_period_total( |
|
761 |
period_start=d_now - datetime.timedelta(days=8), |
|
762 |
include_start=True, |
|
763 |
period_end=d_now - datetime.timedelta(days=2), |
|
764 |
include_end=False, |
|
765 |
criterias=criterias, |
|
766 |
) |
|
767 |
count += sql.get_period_total( |
|
768 |
period_start=d_now - datetime.timedelta(days=30), |
|
769 |
include_start=True, |
|
770 |
period_end=d_now - datetime.timedelta(days=8), |
|
771 |
include_end=False, |
|
772 |
criterias=criterias, |
|
773 |
) |
|
774 |
else: |
|
775 |
# naive count |
|
776 |
count = formdef.data_class().count() |
|
741 |
from wcs import sql |
|
742 | ||
743 |
# 4 * number of submitted forms of last 2 days |
|
744 |
# + 2 * number of submitted forms of last 8 days |
|
745 |
# + 1 * number of submitted forms of last 30 days |
|
746 |
# exclude drafts |
|
747 |
criterias = [Equal('formdef_id', formdef.id), StrictNotEqual('status', 'draft')] |
|
748 |
d_now = datetime.datetime.now() |
|
749 |
count = 4 * sql.get_period_total( |
|
750 |
period_start=d_now - datetime.timedelta(days=2), |
|
751 |
include_start=True, |
|
752 |
criterias=criterias, |
|
753 |
) |
|
754 |
count += 2 * sql.get_period_total( |
|
755 |
period_start=d_now - datetime.timedelta(days=8), |
|
756 |
include_start=True, |
|
757 |
period_end=d_now - datetime.timedelta(days=2), |
|
758 |
include_end=False, |
|
759 |
criterias=criterias, |
|
760 |
) |
|
761 |
count += sql.get_period_total( |
|
762 |
period_start=d_now - datetime.timedelta(days=30), |
|
763 |
include_start=True, |
|
764 |
period_end=d_now - datetime.timedelta(days=8), |
|
765 |
include_end=False, |
|
766 |
criterias=criterias, |
|
767 |
) |
|
777 | 768 |
formdict['count'] = count |
778 | 769 | |
779 | 770 |
formdict['functions'] = {} |
... | ... | |
923 | 914 |
if category_slugs: |
924 | 915 |
categories = Category.select([Contains('url_name', category_slugs)]) |
925 | 916 | |
926 |
if get_publisher().is_using_postgresql(): |
|
927 |
from wcs import sql |
|
917 |
from wcs import sql |
|
928 | 918 | |
929 |
order_by = 'receipt_time' |
|
930 |
if get_request().form.get('sort') == 'desc': |
|
931 |
order_by = '-receipt_time' |
|
932 |
if get_query_flag('include-accessible'): |
|
933 |
user_roles = user.get_roles() |
|
934 |
criterias = [ |
|
919 |
order_by = 'receipt_time' |
|
920 |
if get_request().form.get('sort') == 'desc': |
|
921 |
order_by = '-receipt_time' |
|
922 |
if get_query_flag('include-accessible'): |
|
923 |
user_roles = user.get_roles() |
|
924 |
criterias = [ |
|
925 |
Or( |
|
926 |
[ |
|
927 |
Intersects('concerned_roles_array', user_roles), |
|
928 |
Equal('user_id', str(user.id)), |
|
929 |
] |
|
930 |
) |
|
931 |
] |
|
932 |
else: |
|
933 |
criterias = [Equal('user_id', str(user.id))] |
|
934 |
if category_slugs: |
|
935 |
criterias.append(Contains('category_id', [c.id for c in categories])) |
|
936 | ||
937 |
status_criteria = get_request().form.get('status') or 'all' |
|
938 |
if status_criteria == 'open': |
|
939 |
criterias.append(Equal('is_at_endpoint', False)) |
|
940 |
elif status_criteria == 'done': |
|
941 |
criterias.append(Equal('is_at_endpoint', True)) |
|
942 |
elif status_criteria == 'all': |
|
943 |
pass |
|
944 |
else: |
|
945 |
return HttpResponseBadRequest('invalid status parameter value') |
|
946 | ||
947 |
if include_drafts: |
|
948 |
disabled_formdef_ids = [formdef.id for formdef in FormDef.select() if formdef.is_disabled()] |
|
949 |
if disabled_formdef_ids: |
|
950 |
criterias.append( |
|
935 | 951 |
Or( |
936 | 952 |
[ |
937 |
Intersects('concerned_roles_array', user_roles),
|
|
938 |
Equal('user_id', str(user.id)),
|
|
953 |
StrictNotEqual('status', 'draft'),
|
|
954 |
NotContains('formdef_id', disabled_formdef_ids),
|
|
939 | 955 |
] |
940 | 956 |
) |
941 |
] |
|
942 |
else: |
|
943 |
criterias = [Equal('user_id', str(user.id))] |
|
944 |
if category_slugs: |
|
945 |
criterias.append(Contains('category_id', [c.id for c in categories])) |
|
946 | ||
947 |
status_criteria = get_request().form.get('status') or 'all' |
|
948 |
if status_criteria == 'open': |
|
949 |
criterias.append(Equal('is_at_endpoint', False)) |
|
950 |
elif status_criteria == 'done': |
|
951 |
criterias.append(Equal('is_at_endpoint', True)) |
|
952 |
elif status_criteria == 'all': |
|
953 |
pass |
|
954 |
else: |
|
955 |
return HttpResponseBadRequest('invalid status parameter value') |
|
956 | ||
957 |
if include_drafts: |
|
958 |
disabled_formdef_ids = [formdef.id for formdef in FormDef.select() if formdef.is_disabled()] |
|
959 |
if disabled_formdef_ids: |
|
960 |
criterias.append( |
|
961 |
Or( |
|
962 |
[ |
|
963 |
StrictNotEqual('status', 'draft'), |
|
964 |
NotContains('formdef_id', disabled_formdef_ids), |
|
965 |
] |
|
966 |
) |
|
967 |
) |
|
968 |
else: |
|
969 |
criterias.append(StrictNotEqual('status', 'draft')) |
|
957 |
) |
|
958 |
else: |
|
959 |
criterias.append(StrictNotEqual('status', 'draft')) |
|
970 | 960 | |
971 |
if not include_non_drafts:
|
|
972 |
criterias.append(Equal('status', 'draft'))
|
|
961 |
if not include_non_drafts: |
|
962 |
criterias.append(Equal('status', 'draft')) |
|
973 | 963 | |
974 |
user_forms = sql.AnyFormData.select( |
|
975 |
criterias, |
|
976 |
limit=misc.get_int_or_400(get_request().form.get('limit')), |
|
977 |
offset=misc.get_int_or_400(get_request().form.get('offset')), |
|
978 |
order_by=order_by, |
|
979 |
) |
|
980 |
if get_request().form.get('full') == 'on': |
|
981 |
# load full objects |
|
982 |
formdefs = {x.formdef_id: x.formdef for x in user_forms} |
|
983 |
formdef_user_forms = {} |
|
984 |
for formdef_id, formdef in formdefs.items(): |
|
985 |
formdef_user_forms.update( |
|
986 |
{ |
|
987 |
(formdef_id, x.id): x |
|
988 |
for x in formdef.data_class().select( |
|
989 |
[Contains('id', [x.id for x in user_forms if x.formdef_id == formdef_id])] |
|
990 |
) |
|
991 |
} |
|
992 |
) |
|
993 |
# and put them back in order |
|
994 |
sorted_user_forms_tuples = [(x.formdef_id, x.id) for x in user_forms] |
|
995 |
user_forms = [formdef_user_forms.get(x) for x in sorted_user_forms_tuples] |
|
996 |
else: |
|
997 |
# prefetch evolutions to avoid individual loads when computing |
|
998 |
# formdata.get_visible_status(). |
|
999 |
sql.AnyFormData.load_all_evolutions(user_forms) |
|
964 |
user_forms = sql.AnyFormData.select( |
|
965 |
criterias, |
|
966 |
limit=misc.get_int_or_400(get_request().form.get('limit')), |
|
967 |
offset=misc.get_int_or_400(get_request().form.get('offset')), |
|
968 |
order_by=order_by, |
|
969 |
) |
|
970 |
if get_request().form.get('full') == 'on': |
|
971 |
# load full objects |
|
972 |
formdefs = {x.formdef_id: x.formdef for x in user_forms} |
|
973 |
formdef_user_forms = {} |
|
974 |
for formdef_id, formdef in formdefs.items(): |
|
975 |
formdef_user_forms.update( |
|
976 |
{ |
|
977 |
(formdef_id, x.id): x |
|
978 |
for x in formdef.data_class().select( |
|
979 |
[Contains('id', [x.id for x in user_forms if x.formdef_id == formdef_id])] |
|
980 |
) |
|
981 |
} |
|
982 |
) |
|
983 |
# and put them back in order |
|
984 |
sorted_user_forms_tuples = [(x.formdef_id, x.id) for x in user_forms] |
|
985 |
user_forms = [formdef_user_forms.get(x) for x in sorted_user_forms_tuples] |
|
1000 | 986 |
else: |
1001 |
if get_query_flag('include-accessible'): |
|
1002 |
return HttpResponseBadRequest('not supported') |
|
1003 |
formdefs = FormDef.select() |
|
1004 |
user_forms = [] |
|
1005 |
for formdef in formdefs: |
|
1006 |
user_forms.extend(formdef.data_class().get_with_indexed_value('user_id', user.id)) |
|
1007 |
if category_slugs: |
|
1008 |
user_forms = [f for f in user_forms if f.formdef.category_id in [c.id for c in categories]] |
|
1009 | ||
1010 |
status_criteria = get_request().form.get('status') or 'all' |
|
1011 |
if status_criteria == 'open': |
|
1012 |
user_forms = [x for x in user_forms if not x.is_at_endpoint_status()] |
|
1013 |
elif status_criteria == 'done': |
|
1014 |
user_forms = [x for x in user_forms if x.is_at_endpoint_status()] |
|
1015 |
elif status_criteria == 'all': |
|
1016 |
pass |
|
1017 |
else: |
|
1018 |
return HttpResponseBadRequest('invalid status parameter value') |
|
1019 | ||
1020 |
typed_none = time.gmtime(-(10**10)) |
|
1021 |
user_forms.sort(key=lambda x: x.receipt_time or typed_none) |
|
1022 |
if get_request().form.get('sort') == 'desc': |
|
1023 |
user_forms.reverse() |
|
987 |
# prefetch evolutions to avoid individual loads when computing |
|
988 |
# formdata.get_visible_status(). |
|
989 |
sql.AnyFormData.load_all_evolutions(user_forms) |
|
1024 | 990 |
return user_forms |
1025 | 991 | |
1026 | 992 |
def drafts(self): |
... | ... | |
1056 | 1022 |
raise AccessForbiddenError('user not allowed to query data from others') |
1057 | 1023 |
# mark forms that are readable by querying user |
1058 | 1024 |
user_roles = set(query_user.get_roles()) |
1059 |
if get_publisher().is_using_postgresql(): |
|
1060 |
# use concerned_roles_array attribute that was saved in the |
|
1061 |
# table. |
|
1062 |
for form in forms: |
|
1063 |
form.readable = bool(set(form.concerned_roles_array).intersection(user_roles)) |
|
1064 |
else: |
|
1065 |
# recomputed concerned roles. |
|
1066 |
for form in forms: |
|
1067 |
concerned_roles_array = [str(x) for x in form.concerned_roles if x] |
|
1068 |
form.readable = bool(set(concerned_roles_array).intersection(user_roles)) |
|
1025 |
# use concerned_roles_array attribute that was saved in the |
|
1026 |
# table. |
|
1027 |
for form in forms: |
|
1028 |
form.readable = bool(set(form.concerned_roles_array).intersection(user_roles)) |
|
1069 | 1029 |
# ignore confidential forms |
1070 | 1030 |
forms = [x for x in forms if x.readable or not x.formdef.skip_from_360_view] |
1071 | 1031 | |
... | ... | |
1132 | 1092 |
for field in formdef.fields: |
1133 | 1093 |
if field.type in ('string', 'text', 'email'): |
1134 | 1094 |
criteria_fields.append(st.ILike('f%s' % field.id, query)) |
1135 |
if get_publisher().is_using_postgresql(): |
|
1136 |
criteria_fields.append(st.FtsMatch(query)) |
|
1095 |
criteria_fields.append(st.FtsMatch(query)) |
|
1137 | 1096 |
criterias.append(st.Or(criteria_fields)) |
1138 | 1097 | |
1139 | 1098 |
def as_dict(user): |
wcs/backoffice/cards.py | ||
---|---|---|
213 | 213 |
if self.formdef.is_used(): |
214 | 214 |
return _('Deletion is not possible as it is still used as datasource.') |
215 | 215 | |
216 |
if not get_publisher().is_using_postgresql(): |
|
217 |
return None |
|
218 | ||
219 | 216 |
criterias = [ |
220 | 217 |
StrictNotEqual('status', 'draft'), |
221 | 218 |
Null('anonymised'), |
wcs/backoffice/management.py | ||
---|---|---|
182 | 182 |
forms_without_pending_stuff = [] |
183 | 183 |
forms_with_pending_stuff = [] |
184 | 184 | |
185 |
using_postgresql = get_publisher().is_using_postgresql() |
|
186 |
if using_postgresql: |
|
187 |
from wcs import sql |
|
185 |
from wcs import sql |
|
188 | 186 | |
189 |
actionable_counts = sql.get_actionable_counts(user_roles)
|
|
190 |
total_counts = sql.get_total_counts(user_roles)
|
|
187 |
actionable_counts = sql.get_actionable_counts(user_roles) |
|
188 |
total_counts = sql.get_total_counts(user_roles) |
|
191 | 189 | |
192 | 190 |
def append_form_entry(formdef): |
193 |
if using_postgresql: |
|
194 |
count_forms = total_counts.get(formdef.id) or 0 |
|
195 |
waiting_forms_count = actionable_counts.get(formdef.id) or 0 |
|
196 |
else: |
|
197 |
formdef_data_class = formdef.data_class() |
|
198 |
count_forms = formdef_data_class.count() - len( |
|
199 |
formdef_data_class.get_ids_with_indexed_value('status', 'draft') |
|
200 |
) |
|
201 |
waiting_forms_count = formdef_data_class.get_actionable_count(user_roles) |
|
191 |
count_forms = total_counts.get(formdef.id) or 0 |
|
192 |
waiting_forms_count = actionable_counts.get(formdef.id) or 0 |
|
202 | 193 |
if waiting_forms_count == 0: |
203 | 194 |
forms_without_pending_stuff.append((formdef, waiting_forms_count, count_forms)) |
204 | 195 |
else: |
... | ... | |
211 | 202 | |
212 | 203 |
def top_action_links(r): |
213 | 204 |
r += htmltext('<span class="actions">') |
214 |
if ( |
|
215 |
get_publisher().is_using_postgresql() |
|
216 |
and get_publisher().get_site_option('postgresql_views') != 'false' |
|
217 |
): |
|
218 |
r += htmltext('<a href="listing">%s</a>') % _('Global View') |
|
205 |
r += htmltext('<a href="listing">%s</a>') % _('Global View') |
|
219 | 206 |
for formdef in formdefs: |
220 | 207 |
if formdef.geolocations: |
221 | 208 |
r += htmltext(' <a href="map">%s</a>') % _('Map View') |
... | ... | |
261 | 248 | |
262 | 249 |
def lookup(self): |
263 | 250 |
query = get_request().form.get('query', '').strip() |
264 |
if get_publisher().is_using_postgresql(): |
|
265 |
from wcs import sql |
|
251 |
from wcs import sql |
|
252 | ||
253 |
formdatas = sql.AnyFormData.select([Equal('id_display', query)]) |
|
254 |
if formdatas: |
|
255 |
return redirect(formdatas[0].get_url(backoffice=True)) |
|
266 | 256 | |
267 |
formdatas = sql.AnyFormData.select([Equal('id_display', query)]) |
|
268 |
if formdatas: |
|
269 |
return redirect(formdatas[0].get_url(backoffice=True)) |
|
270 | 257 |
if any(x for x in FormDef.select(lightweight=True) if x.enable_tracking_codes): |
271 | 258 |
try: |
272 | 259 |
tracking_code = get_publisher().tracking_code_class.get(query) |
... | ... | |
433 | 420 |
period_start = parsed_values.get('period_start') |
434 | 421 |
period_end = parsed_values.get('period_end') |
435 | 422 | |
436 |
if get_publisher().is_using_postgresql(): |
|
437 |
from wcs import sql |
|
438 | ||
439 |
formdef_totals = sql.get_formdef_totals(period_start, period_end, criterias) |
|
440 |
counts = {str(x): y for x, y in formdef_totals} |
|
441 |
else: |
|
442 |
for formdef in formdefs: |
|
443 |
values = formdef.data_class().select(criterias) |
|
444 |
counts[formdef.id] = len(values) |
|
423 |
from wcs import sql |
|
445 | 424 | |
446 |
do_graphs = False |
|
447 |
if ( |
|
448 |
get_publisher().is_using_postgresql() |
|
449 |
and get_publisher().get_site_option('postgresql_views') != 'false' |
|
450 |
): |
|
451 |
do_graphs = True |
|
425 |
formdef_totals = sql.get_formdef_totals(period_start, period_end, criterias) |
|
426 |
counts = {str(x): y for x, y in formdef_totals} |
|
452 | 427 | |
453 | 428 |
r += htmltext('<p>%s %s</p>') % (_('Total count:'), sum(counts.values())) |
454 | 429 | |
455 |
if do_graphs: |
|
456 |
r += htmltext('<div class="splitcontent-left">') |
|
430 |
r += htmltext('<div class="splitcontent-left">') |
|
457 | 431 |
cats = Category.select() |
458 | 432 |
for cat in cats: |
459 | 433 |
category_formdefs = [x for x in formdefs if x.category_id == cat.id] |
... | ... | |
462 | 436 |
category_formdefs = [x for x in formdefs if x.category_id is None] |
463 | 437 |
r += self.category_global_stats(_('Misc'), category_formdefs, counts) |
464 | 438 | |
465 |
if do_graphs: |
|
466 |
r += htmltext('</div>') |
|
467 |
r += htmltext('<div class="splitcontent-right">') |
|
468 |
r += do_graphs_section(period_start, period_end, criterias=[StrictNotEqual('status', 'draft')]) |
|
469 |
r += htmltext('</div>') |
|
439 |
r += htmltext('</div>') |
|
440 |
r += htmltext('<div class="splitcontent-right">') |
|
441 |
r += do_graphs_section(period_start, period_end, criterias=[StrictNotEqual('status', 'draft')]) |
|
442 |
r += htmltext('</div>') |
|
470 | 443 | |
471 | 444 |
return r.getvalue() |
472 | 445 | |
... | ... | |
597 | 570 |
return r.getvalue() |
598 | 571 | |
599 | 572 |
def listing(self): |
600 |
if not get_publisher().is_using_postgresql(): |
|
601 |
raise errors.TraversalError() |
|
602 | ||
603 | 573 |
get_response().add_javascript(['wcs.listing.js']) |
604 | 574 |
from wcs import sql |
605 | 575 | |
... | ... | |
731 | 701 |
return rt.getvalue() |
732 | 702 | |
733 | 703 |
def count(self): |
734 |
if not get_publisher().is_using_postgresql(): |
|
735 |
raise errors.TraversalError() |
|
736 | 704 |
if not (FormDef.exists()): |
737 | 705 |
return misc.json_response({'count': 0}) |
738 | 706 |
from wcs import sql |
... | ... | |
754 | 722 |
return json.dumps(geojson_formdatas(formdatas, fields=fields), cls=misc.JSONEncoder) |
755 | 723 | |
756 | 724 |
def map(self): |
757 |
if not get_publisher().is_using_postgresql(): |
|
758 |
raise errors.TraversalError() |
|
759 | 725 |
get_response().add_javascript(['wcs.listing.js', 'qommon.map.js']) |
760 | 726 |
html_top('management', _('Global Map')) |
761 | 727 |
r = TemplateIO(html=True) |
... | ... | |
1051 | 1017 |
'user-id', |
1052 | 1018 |
'user-function', |
1053 | 1019 |
'submission-agent-id', |
1020 |
'date', |
|
1054 | 1021 |
] |
1055 |
if get_publisher().is_using_postgresql(): |
|
1056 |
types.append('date') |
|
1057 | 1022 |
return types |
1058 | 1023 | |
1059 | 1024 |
def get_filter_sidebar( |
... | ... | |
1200 | 1165 |
('pending', C_('formdata|Open'), None), |
1201 | 1166 |
('done', _('Done'), None), |
1202 | 1167 |
] |
1203 |
if mode == 'stats' and not get_publisher().is_using_postgresql(): |
|
1204 |
filters = [x for x in filters if x[0] != 'waiting'] |
|
1205 | 1168 |
for status in waitpoint_status: |
1206 | 1169 |
filters.append((status.id, status.name, status.colour)) |
1207 | 1170 |
for filter_id, filter_label, filter_colour in filters: |
... | ... | |
1282 | 1245 |
elif filter_field.type in ('item', 'items'): |
1283 | 1246 |
filter_field.required = False |
1284 | 1247 | |
1285 |
if get_publisher().is_using_postgresql(): |
|
1286 |
# Get options from existing formdatas. |
|
1287 |
# This allows for options that don't appear anymore in the |
|
1288 |
# data source to be listed (for example because the field |
|
1289 |
# is using a parametrized URL depending on unavailable |
|
1290 |
# variables, or simply returning different results now). |
|
1291 |
display_mode = 'select' |
|
1292 |
if filter_field.type == 'item' and filter_field.get_display_mode() == 'autocomplete': |
|
1293 |
display_mode = 'select2' |
|
1294 | ||
1295 |
if display_mode == 'select': |
|
1296 |
options = self.get_item_filter_options( |
|
1297 |
filter_field, |
|
1298 |
selected_filter, |
|
1299 |
selected_filter_operator, |
|
1300 |
criterias, |
|
1301 |
) |
|
1302 |
options = [(x[0], x[1], x[0]) for x in options] |
|
1303 |
options.insert(0, (None, '', '')) |
|
1304 |
attrs = {'data-refresh-options': str(filter_field.contextual_id)} |
|
1305 |
else: |
|
1306 |
options = [(filter_field_value, filter_field_value or '', filter_field_value or '')] |
|
1307 |
attrs = {'data-remote-options': str(filter_field.contextual_id)} |
|
1308 |
get_response().add_javascript( |
|
1309 |
['jquery.js', '../../i18n.js', 'qommon.forms.js', 'select2.js'] |
|
1310 |
) |
|
1311 |
get_response().add_css_include('select2.css') |
|
1312 |
if self.view and self.view.visibility == 'datasource': |
|
1313 |
options.append(('{}', _('custom value'), '{}')) |
|
1314 |
if filter_field_value and filter_field_value not in [x[0] for x in options]: |
|
1315 |
options.append((filter_field_value, filter_field_value, filter_field_value)) |
|
1316 |
attrs['data-allow-template'] = 'true' |
|
1317 | ||
1318 |
widget = SingleSelectWidget( |
|
1319 |
filter_field_key, |
|
1320 |
title=filter_field.label, |
|
1321 |
options=options, |
|
1322 |
value=filter_field_value, |
|
1323 |
render_br=False, |
|
1324 |
attrs=attrs, |
|
1248 |
# Get options from existing formdatas. |
|
1249 |
# This allows for options that don't appear anymore in the |
|
1250 |
# data source to be listed (for example because the field |
|
1251 |
# is using a parametrized URL depending on unavailable |
|
1252 |
# variables, or simply returning different results now). |
|
1253 |
display_mode = 'select' |
|
1254 |
if filter_field.type == 'item' and filter_field.get_display_mode() == 'autocomplete': |
|
1255 |
display_mode = 'select2' |
|
1256 | ||
1257 |
if display_mode == 'select': |
|
1258 |
options = self.get_item_filter_options( |
|
1259 |
filter_field, |
|
1260 |
selected_filter, |
|
1261 |
selected_filter_operator, |
|
1262 |
criterias, |
|
1325 | 1263 |
) |
1326 |
r += render_widget(widget, operators) |
|
1327 | ||
1264 |
options = [(x[0], x[1], x[0]) for x in options] |
|
1265 |
options.insert(0, (None, '', '')) |
|
1266 |
attrs = {'data-refresh-options': str(filter_field.contextual_id)} |
|
1328 | 1267 |
else: |
1329 |
# In pickle environments, get options from data source |
|
1330 |
options = filter_field.get_options() |
|
1331 |
if options: |
|
1332 |
if len(options[0]) == 2: |
|
1333 |
options = [(x[0], x[1], x[0]) for x in options] |
|
1334 |
options.insert(0, (None, '', '')) |
|
1335 |
widget = SingleSelectWidget( |
|
1336 |
filter_field_key, |
|
1337 |
title=filter_field.label, |
|
1338 |
options=options, |
|
1339 |
value=filter_field_value, |
|
1340 |
render_br=False, |
|
1341 |
) |
|
1342 |
r += render_widget(widget, operators) |
|
1343 |
else: |
|
1344 |
# and fall back on a string widget if there are none. |
|
1345 |
widget = StringWidget( |
|
1346 |
filter_field_key, |
|
1347 |
title=filter_field.label, |
|
1348 |
value=filter_field_value, |
|
1349 |
render_br=False, |
|
1350 |
) |
|
1351 |
r += render_widget(widget, operators) |
|
1268 |
options = [(filter_field_value, filter_field_value or '', filter_field_value or '')] |
|
1269 |
attrs = {'data-remote-options': str(filter_field.contextual_id)} |
|
1270 |
get_response().add_javascript( |
|
1271 |
['jquery.js', '../../i18n.js', 'qommon.forms.js', 'select2.js'] |
|
1272 |
) |
|
1273 |
get_response().add_css_include('select2.css') |
|
1274 |
if self.view and self.view.visibility == 'datasource': |
|
1275 |
options.append(('{}', _('custom value'), '{}')) |
|
1276 |
if filter_field_value and filter_field_value not in [x[0] for x in options]: |
|
1277 |
options.append((filter_field_value, filter_field_value, filter_field_value)) |
|
1278 |
attrs['data-allow-template'] = 'true' |
|
1279 | ||
1280 |
widget = SingleSelectWidget( |
|
1281 |
filter_field_key, |
|
1282 |
title=filter_field.label, |
|
1283 |
options=options, |
|
1284 |
value=filter_field_value, |
|
1285 |
render_br=False, |
|
1286 |
attrs=attrs, |
|
1287 |
) |
|
1288 |
r += render_widget(widget, operators) |
|
1352 | 1289 | |
1353 | 1290 |
elif filter_field.type == 'bool': |
1354 | 1291 |
options = [(None, '', ''), (True, _('Yes'), 'true'), (False, _('No'), 'false')] |
... | ... | |
1421 | 1358 |
if limit: |
1422 | 1359 |
r += htmltext('<input type="hidden" name="limit" value="%s"/>') % limit |
1423 | 1360 | |
1424 |
if get_publisher().is_using_postgresql(): |
|
1425 |
if order_by is None: |
|
1426 |
order_by = get_publisher().get_site_option('default-sort-order') or '-receipt_time' |
|
1427 |
r += htmltext('<input type="hidden" name="order_by" value="%s"/>') % order_by |
|
1361 |
if order_by is None: |
|
1362 |
order_by = get_publisher().get_site_option('default-sort-order') or '-receipt_time' |
|
1363 |
r += htmltext('<input type="hidden" name="order_by" value="%s"/>') % order_by |
|
1428 | 1364 | |
1429 |
if get_publisher().is_using_postgresql(): |
|
1430 |
r += htmltext('<h3>%s</h3>') % self.search_label |
|
1431 |
if get_request().form.get('q'): |
|
1432 |
q = force_text(get_request().form.get('q')) |
|
1433 |
r += htmltext('<input class="inline-input" name="q" value="%s">') % force_str(q) |
|
1434 |
else: |
|
1435 |
r += htmltext('<input class="inline-input" name="q">') |
|
1436 |
r += htmltext('<button class="side-button">%s</button>') % _('Search') |
|
1365 |
r += htmltext('<h3>%s</h3>') % self.search_label |
|
1366 |
if get_request().form.get('q'): |
|
1367 |
q = force_text(get_request().form.get('q')) |
|
1368 |
r += htmltext('<input class="inline-input" name="q" value="%s">') % force_str(q) |
|
1369 |
else: |
|
1370 |
r += htmltext('<input class="inline-input" name="q">') |
|
1371 |
r += htmltext('<button class="side-button">%s</button>') % _('Search') |
|
1437 | 1372 | |
1438 | 1373 |
r += self.get_filter_sidebar( |
1439 | 1374 |
selected_filter=selected_filter, |
... | ... | |
1664 | 1599 |
yield FakeField('last_update_time', 'last_update_time', _('Last Modified')) |
1665 | 1600 | |
1666 | 1601 |
# user fields |
1667 |
if not get_publisher().is_using_postgresql(): |
|
1668 |
# full name of user, this will load individual user objects to get it |
|
1669 |
yield FakeField('user-label', 'user-label', _('User Label')) |
|
1670 |
else: |
|
1671 |
# user-label field but as a custom field, to get full name of user |
|
1672 |
# using a sql join clause. |
|
1673 |
yield UserLabelRelatedField() |
|
1674 |
for field in get_publisher().user_class.get_fields(): |
|
1675 |
if not hasattr(field, 'get_view_value'): |
|
1676 |
continue |
|
1677 |
field.has_relations = True |
|
1678 |
yield UserRelatedField(field) |
|
1602 |
# user-label field but as a custom field, to get full name of user |
|
1603 |
# using a sql join clause. |
|
1604 |
yield UserLabelRelatedField() |
|
1605 |
for field in get_publisher().user_class.get_fields(): |
|
1606 |
if not hasattr(field, 'get_view_value'): |
|
1607 |
continue |
|
1608 |
field.has_relations = True |
|
1609 |
yield UserRelatedField(field) |
|
1679 | 1610 | |
1680 | 1611 |
for field in self.formdef.iter_fields(include_block_fields=True): |
1681 | 1612 |
if getattr(field, 'block_field', None): |
... | ... | |
1683 | 1614 |
# not yet |
1684 | 1615 |
continue |
1685 | 1616 |
yield field |
1686 |
if not get_publisher().is_using_postgresql(): |
|
1687 |
continue |
|
1688 | 1617 |
if field.key == 'block': |
1689 | 1618 |
continue |
1690 | 1619 |
if getattr(field, 'block_field', None): |
... | ... | |
2145 | 2074 |
selected_filter_operator = self.get_filter_operator_from_query() |
2146 | 2075 |
criterias = self.get_criterias_from_query() |
2147 | 2076 | |
2148 |
if get_publisher().is_using_postgresql(): |
|
2149 |
# only enable pagination in SQL mode, as we do not have sorting in |
|
2150 |
# the other case. |
|
2151 |
limit = misc.get_int_or_400( |
|
2152 |
get_request().form.get('limit', get_publisher().get_site_option('default-page-size') or 20) |
|
2153 |
) |
|
2154 |
else: |
|
2155 |
limit = misc.get_int_or_400(get_request().form.get('limit', 0)) |
|
2077 |
limit = misc.get_int_or_400( |
|
2078 |
get_request().form.get('limit', get_publisher().get_site_option('default-page-size') or 20) |
|
2079 |
) |
|
2156 | 2080 |
offset = misc.get_int_or_400(get_request().form.get('offset', 0)) |
2157 | 2081 |
order_by = misc.get_order_by_or_400(get_request().form.get('order_by')) |
2158 | 2082 |
if self.view and not order_by: |
... | ... | |
2251 | 2175 |
def submit_multi(self, action, selected_filter, selected_filter_operator, query, criterias): |
2252 | 2176 |
item_ids = get_request().form['select[]'] |
2253 | 2177 |
if '_all' in item_ids: |
2254 |
if get_publisher().is_using_postgresql(): |
|
2255 |
criterias.append(Null('anonymised')) |
|
2178 |
criterias.append(Null('anonymised')) |
|
2256 | 2179 |
item_ids = FormDefUI(self.formdef).get_listing_item_ids( |
2257 | 2180 |
selected_filter, |
2258 | 2181 |
selected_filter_operator, |
... | ... | |
2444 | 2367 |
offset=offset, |
2445 | 2368 |
limit=limit, |
2446 | 2369 |
)[0] |
2447 |
if get_publisher().is_using_postgresql(): |
|
2448 |
self.formdef.data_class().load_all_evolutions(items) |
|
2370 |
self.formdef.data_class().load_all_evolutions(items) |
|
2449 | 2371 |
digest_key = 'default' |
2450 | 2372 |
if self.view and isinstance(self.formdef, CardDef): |
2451 | 2373 |
view_digest_key = 'custom-view:%s' % self.view.get_url_slug() |
... | ... | |
2455 | 2377 |
output = [] |
2456 | 2378 |
prefetched_users = None |
2457 | 2379 |
prefetched_roles = None |
2458 |
if get_publisher().is_using_postgresql: |
|
2459 |
prefetched_users = { |
|
2460 |
str(x.id): x |
|
2461 |
for x in get_publisher().user_class.get_ids( |
|
2462 |
[x.user_id for x in items if x.user_id], ignore_errors=True |
|
2463 |
) |
|
2464 |
if x is not None |
|
2465 |
} |
|
2466 |
role_ids = set((self.formdef.workflow_roles or {}).values()) |
|
2467 |
for filled in items: |
|
2468 |
if filled.workflow_roles: |
|
2469 |
for value in filled.workflow_roles.values(): |
|
2470 |
if not isinstance(value, list): |
|
2471 |
value = [value] |
|
2472 |
role_ids |= set(value) |
|
2473 |
prefetched_roles = { |
|
2474 |
str(x.id): x |
|
2475 |
for x in get_publisher().role_class.get_ids(role_ids, ignore_errors=True) |
|
2476 |
if x is not None |
|
2477 |
} |
|
2380 |
prefetched_users = { |
|
2381 |
str(x.id): x |
|
2382 |
for x in get_publisher().user_class.get_ids( |
|
2383 |
[x.user_id for x in items if x.user_id], ignore_errors=True |
|
2384 |
) |
|
2385 |
if x is not None |
|
2386 |
} |
|
2387 |
role_ids = set((self.formdef.workflow_roles or {}).values()) |
|
2388 |
for filled in items: |
|
2389 |
if filled.workflow_roles: |
|
2390 |
for value in filled.workflow_roles.values(): |
|
2391 |
if not isinstance(value, list): |
|
2392 |
value = [value] |
|
2393 |
role_ids |= set(value) |
|
2394 |
prefetched_roles = { |
|
2395 |
str(x.id): x |
|
2396 |
for x in get_publisher().role_class.get_ids(role_ids, ignore_errors=True) |
|
2397 |
if x is not None |
|
2398 |
} |
|
2478 | 2399 |
for filled in items: |
2479 | 2400 |
data = filled.get_json_export_dict( |
2480 | 2401 |
include_files=False, |
... | ... | |
2717 | 2638 |
get_response().filter['sidebar'] = self.get_formdata_sidebar() + self.get_stats_sidebar( |
2718 | 2639 |
selected_filter |
2719 | 2640 |
) |
2720 |
do_graphs = get_publisher().is_using_postgresql() |
|
2721 | 2641 | |
2722 | 2642 |
displayed_criterias = None |
2723 | 2643 |
if selected_filter and selected_filter != 'all': |
... | ... | |
2749 | 2669 |
criterias = [StrictNotEqual('status', 'draft')] + displayed_criterias |
2750 | 2670 | |
2751 | 2671 |
values = self.formdef.data_class().select(criterias) |
2752 |
if get_publisher().is_using_postgresql(): |
|
2753 |
# load all evolutions in a single batch, to avoid as many query as |
|
2754 |
# there are formdata when computing resolution times statistics. |
|
2755 |
self.formdef.data_class().load_all_evolutions(values) |
|
2672 |
# load all evolutions in a single batch, to avoid as many query as |
|
2673 |
# there are formdata when computing resolution times statistics. |
|
2674 |
self.formdef.data_class().load_all_evolutions(values) |
|
2756 | 2675 | |
2757 | 2676 |
r += htmltext('<div id="statistics">') |
2758 | 2677 |
if displayed_criterias: |
... | ... | |
2764 | 2683 |
if criteria_label: |
2765 | 2684 |
r += htmltext('<li>%s</li>') % criteria_label |
2766 | 2685 |
r += htmltext('</ul></div>') |
2767 |
if do_graphs: |
|
2768 |
r += htmltext('<div class="splitcontent-left">') |
|
2686 |
r += htmltext('<div class="splitcontent-left">') |
|
2769 | 2687 | |
2770 | 2688 |
no_forms = len(values) |
2771 | 2689 |
r += htmltext('<div class="bo-block">') |
... | ... | |
2799 | 2717 |
r += stats_times |
2800 | 2718 |
r += htmltext('</div>') |
2801 | 2719 | |
2802 |
if do_graphs: |
|
2803 |
r += htmltext('</div>') |
|
2804 |
r += htmltext('<div class="splitcontent-right">') |
|
2805 |
criterias.append(Equal('formdef_id', int(self.formdef.id))) |
|
2806 |
r += do_graphs_section(criterias=criterias) |
|
2807 |
r += htmltext('</div>') |
|
2720 |
r += htmltext('</div>') |
|
2721 |
r += htmltext('<div class="splitcontent-right">') |
|
2722 |
criterias.append(Equal('formdef_id', int(self.formdef.id))) |
|
2723 |
r += do_graphs_section(criterias=criterias) |
|
2724 |
r += htmltext('</div>') |
|
2808 | 2725 | |
2809 | 2726 |
r += htmltext('</div>') # id="statistics" |
2810 | 2727 | |
... | ... | |
3165 | 3082 |
if formdata.formdef.lateral_template: |
3166 | 3083 |
r += htmltext('<div data-async-url="%slateral-block"></div>' % formdata.get_url(backoffice=True)) |
3167 | 3084 | |
3168 |
if ( |
|
3169 |
not isinstance(formdata.formdef, CardDef) |
|
3170 |
and formdata.user_id |
|
3171 |
and get_publisher().is_using_postgresql() |
|
3172 |
): |
|
3085 |
if not isinstance(formdata.formdef, CardDef) and formdata.user_id: |
|
3173 | 3086 |
r += htmltext( |
3174 | 3087 |
'<div data-async-url="%suser-pending-forms"></div>' % formdata.get_url(backoffice=True) |
3175 | 3088 |
) |
wcs/backoffice/submission.py | ||
---|---|---|
202 | 202 |
return |
203 | 203 | |
204 | 204 |
data_class = self.formdef.data_class() |
205 |
if get_publisher().is_using_postgresql(): |
|
206 |
has = bool( |
|
207 |
data_class.count([StrictNotEqual('status', 'draft'), Equal('user_id', formdata.user_id)]) |
|
208 |
) |
|
209 |
else: |
|
210 |
has = any( |
|
211 |
x for x in data_class.get_with_indexed_value('user_id', formdata.user_id) if not x.is_draft() |
|
212 |
) |
|
213 |
context['user_has_already_one_such_form'] = has |
|
205 |
context['user_has_already_one_such_form'] = bool( |
|
206 |
data_class.count([StrictNotEqual('status', 'draft'), Equal('user_id', formdata.user_id)]) |
|
207 |
) |
|
214 | 208 | |
215 | 209 |
def get_sidebar(self, data): |
216 | 210 |
r = TemplateIO(html=True) |
wcs/carddef.py | ||
---|---|---|
60 | 60 |
# carddef |
61 | 61 |
if data_class._formdef is self: |
62 | 62 |
return data_class |
63 |
if (get_publisher().is_using_postgresql() and not mode == 'files') or mode == 'sql':
|
|
63 |
if (not mode == 'files') or mode == 'sql': |
|
64 | 64 |
from . import sql |
65 | 65 | |
66 | 66 |
table_name = sql.get_formdef_table_name(self) |
wcs/ctl/delete_tenant.py | ||
---|---|---|
51 | 51 |
deletion_date = datetime.now().strftime('%Y%m%d_%H%M%S_%f') |
52 | 52 |
os.rename(pub.app_dir, pub.app_dir + '_removed_%s.invalid' % deletion_date) |
53 | 53 | |
54 |
# do this only if the wcs has a postgresql configuration |
|
55 |
if pub.is_using_postgresql(): |
|
56 |
postgresql_cfg = {} |
|
57 |
for k, v in pub.cfg['postgresql'].items(): |
|
58 |
if v and isinstance(v, str): |
|
59 |
postgresql_cfg[k] = v |
|
60 | ||
61 |
# if there's a createdb-connection-params, we can do a DROP DATABASE with |
|
62 |
# the option --force-drop, rename it if not |
|
63 |
createdb_cfg = pub.cfg['postgresql'].get('createdb-connection-params', {}) |
|
64 |
createdb = True |
|
65 |
if not createdb_cfg: |
|
66 |
createdb_cfg = postgresql_cfg |
|
67 |
createdb = False |
|
68 |
if 'database' in createdb_cfg: |
|
69 |
createdb_cfg['dbname'] = createdb_cfg.pop('database') |
|
70 |
try: |
|
71 |
pgconn = psycopg2.connect(**createdb_cfg) |
|
72 |
except psycopg2.Error as e: |
|
73 |
print( |
|
74 |
'failed to connect to postgresql (%s)' % psycopg2.errorcodes.lookup(e.pgcode), |
|
75 |
file=sys.stderr, |
|
76 |
) |
|
77 |
return |
|
78 | ||
79 |
pgconn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) |
|
80 |
cur = pgconn.cursor() |
|
81 |
dbname = postgresql_cfg.get('dbname') or postgresql_cfg.get('database') |
|
82 |
try: |
|
83 |
if createdb: |
|
84 |
if options.force_drop: |
|
85 |
cur.execute('DROP DATABASE %s' % dbname) |
|
86 |
else: |
|
87 |
cur.execute( |
|
88 |
'ALTER DATABASE %s RENAME TO removed_%s_%s' % (dbname, deletion_date, dbname) |
|
89 |
) |
|
54 |
postgresql_cfg = {} |
|
55 |
for k, v in pub.cfg['postgresql'].items(): |
|
56 |
if v and isinstance(v, str): |
|
57 |
postgresql_cfg[k] = v |
|
58 | ||
59 |
# if there's a createdb-connection-params, we can do a DROP DATABASE with |
|
60 |
# the option --force-drop, rename it if not |
|
61 |
createdb_cfg = pub.cfg['postgresql'].get('createdb-connection-params', {}) |
|
62 |
createdb = True |
|
63 |
if not createdb_cfg: |
|
64 |
createdb_cfg = postgresql_cfg |
|
65 |
createdb = False |
|
66 |
if 'database' in createdb_cfg: |
|
67 |
createdb_cfg['dbname'] = createdb_cfg.pop('database') |
|
68 |
try: |
|
69 |
pgconn = psycopg2.connect(**createdb_cfg) |
|
70 |
except psycopg2.Error as e: |
|
71 |
print( |
|
72 |
'failed to connect to postgresql (%s)' % psycopg2.errorcodes.lookup(e.pgcode), |
|
73 |
file=sys.stderr, |
|
74 |
) |
|
75 |
return |
|
76 | ||
77 |
pgconn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) |
|
78 |
cur = pgconn.cursor() |
|
79 |
dbname = postgresql_cfg.get('dbname') or postgresql_cfg.get('database') |
|
80 |
try: |
|
81 |
if createdb: |
|
82 |
if options.force_drop: |
|
83 |
cur.execute('DROP DATABASE %s' % dbname) |
|
90 | 84 |
else: |
91 |
cur.execute( |
|
92 |
"""SELECT table_name |
|
93 |
FROM information_schema.tables |
|
94 |
WHERE table_schema = 'public' |
|
95 |
AND table_type = 'BASE TABLE'""" |
|
96 |
) |
|
97 | ||
98 |
tables_names = [x[0] for x in cur.fetchall()] |
|
99 | ||
100 |
if options.force_drop: |
|
101 |
for table_name in tables_names: |
|
102 |
cur.execute('DROP TABLE %s CASCADE' % table_name) |
|
103 | ||
104 |
else: |
|
105 |
schema_name = 'removed_%s_%s' % (deletion_date, dbname) |
|
106 |
cur.execute("CREATE SCHEMA %s" % schema_name[:63]) |
|
107 |
for table_name in tables_names: |
|
108 |
cur.execute('ALTER TABLE %s SET SCHEMA %s' % (table_name, schema_name[:63])) |
|
109 | ||
110 |
except psycopg2.Error as e: |
|
111 |
print( |
|
112 |
'failed to alter database %s: (%s)' % (dbname, psycopg2.errorcodes.lookup(e.pgcode)), |
|
113 |
file=sys.stderr, |
|
85 |
cur.execute('ALTER DATABASE %s RENAME TO removed_%s_%s' % (dbname, deletion_date, dbname)) |
|
86 |
else: |
|
87 |
cur.execute( |
|
88 |
"""SELECT table_name |
|
89 |
FROM information_schema.tables |
|
90 |
WHERE table_schema = 'public' |
|
91 |
AND table_type = 'BASE TABLE'""" |
|
114 | 92 |
) |
115 |
return |
|
116 | 93 | |
117 |
cur.close() |
|
94 |
tables_names = [x[0] for x in cur.fetchall()] |
|
95 | ||
96 |
if options.force_drop: |
|
97 |
for table_name in tables_names: |
|
98 |
cur.execute('DROP TABLE %s CASCADE' % table_name) |
|
99 | ||
100 |
else: |
|
101 |
schema_name = 'removed_%s_%s' % (deletion_date, dbname) |
|
102 |
cur.execute("CREATE SCHEMA %s" % schema_name[:63]) |
|
103 |
for table_name in tables_names: |
|
104 |
cur.execute('ALTER TABLE %s SET SCHEMA %s' % (table_name, schema_name[:63])) |
|
105 | ||
106 |
except psycopg2.Error as e: |
|
107 |
print( |
|
108 |
'failed to alter database %s: (%s)' % (dbname, psycopg2.errorcodes.lookup(e.pgcode)), |
|
109 |
file=sys.stderr, |
|
110 |
) |
|
111 |
return |
|
112 | ||
113 |
cur.close() |
|
118 | 114 | |
119 | 115 | |
120 | 116 |
CmdDeleteTenant.register() |
wcs/ctl/rebuild_indexes.py | ||
---|---|---|
28 | 28 |
if destroy: |
29 | 29 |
Role.destroy_indexes() |
30 | 30 |
Role.rebuild_indexes() |
31 |
if pub.is_using_postgresql(): |
|
32 |
return |
|
33 |
from wcs.users import User |
|
34 | ||
35 |
if destroy: |
|
36 |
User.destroy_indexes() |
|
37 |
User.rebuild_indexes() |
|
38 |
for formdef in FormDef.select(): |
|
39 |
formdata = formdef.data_class() |
|
40 |
if destroy: |
|
41 |
formdata.destroy_indexes() |
|
42 |
formdata.rebuild_indexes() |
|
43 | 31 | |
44 | 32 | |
45 | 33 |
class CmdRebuildIndexes(Command): |
wcs/formdata.py | ||
---|---|---|
424 | 424 | |
425 | 425 |
@classmethod |
426 | 426 |
def get_actionable_count(cls, user_roles): |
427 |
if get_publisher().is_using_postgresql(): |
|
428 |
statuses = ['wf-%s' % x.id for x in cls._formdef.workflow.get_not_endpoint_status()] |
|
429 |
criterias = [ |
|
430 |
Intersects('actions_roles_array', user_roles), |
|
431 |
Contains('status', statuses), |
|
432 |
Null('anonymised'), |
|
433 |
] |
|
434 |
return cls.count(criterias) |
|
435 |
else: |
|
436 |
return len(cls.get_actionable_ids(user_roles)) |
|
427 |
statuses = ['wf-%s' % x.id for x in cls._formdef.workflow.get_not_endpoint_status()] |
|
428 |
criterias = [ |
|
429 |
Intersects('actions_roles_array', user_roles), |
|
430 |
Contains('status', statuses), |
|
431 |
Null('anonymised'), |
|
432 |
] |
|
433 |
return cls.count(criterias) |
|
437 | 434 | |
438 | 435 |
@classmethod |
439 | 436 |
def get_actionable_ids_criteria(cls, user_roles): |
... | ... | |
442 | 439 | |
443 | 440 |
@classmethod |
444 | 441 |
def get_actionable_ids(cls, user_roles): |
445 |
if get_publisher().is_using_postgresql(): |
|
446 |
return cls.keys([cls.get_actionable_ids_criteria(user_roles)]) |
|
447 |
else: |
|
448 |
statuses = ['wf-%s' % x.id for x in cls._formdef.workflow.get_not_endpoint_status()] |
|
449 |
actions_ids = set() |
|
450 |
for role in user_roles: |
|
451 |
actions_ids |= set(cls.get_ids_with_indexed_value('actions_roles', str(role))) |
|
452 |
open_ids = [] |
|
453 |
for status_id in statuses: |
|
454 |
open_ids.extend(cls.get_ids_with_indexed_value('status', status_id)) |
|
455 |
return list(actions_ids.intersection(open_ids)) |
|
442 |
return cls.keys([cls.get_actionable_ids_criteria(user_roles)]) |
|
456 | 443 | |
457 | 444 |
@classmethod |
458 | 445 |
def get_submission_channels(cls): |
wcs/formdef.py | ||
---|---|---|
44 | 44 |
from .qommon.form import Form, HtmlWidget, UploadedFile |
45 | 45 |
from .qommon.misc import JSONEncoder, get_as_datetime, is_attachment, is_upload, simplify, xml_node_text |
46 | 46 |
from .qommon.publisher import get_publisher_class |
47 |
from .qommon.storage import Equal, StorableObject, StrictNotEqual, fix_key
|
|
47 |
from .qommon.storage import Equal, StorableObject, fix_key |
|
48 | 48 |
from .qommon.substitution import Substitutions |
49 | 49 |
from .qommon.template import Template |
50 | 50 |
from .roles import logged_users_role |
... | ... | |
329 | 329 |
@classmethod |
330 | 330 |
def remove_object(cls, id): |
331 | 331 |
super().remove_object(id) |
332 |
if get_publisher().is_using_postgresql() and cls == FormDef:
|
|
332 |
if cls == FormDef: |
|
333 | 333 |
# recreate global views so they don't reference formdata from |
334 | 334 |
# deleted formefs |
335 | 335 |
from . import sql |
... | ... | |
352 | 352 |
# formdef |
353 | 353 |
if data_class._formdef is self: |
354 | 354 |
return data_class |
355 |
if (get_publisher().is_using_postgresql() and not mode == 'files') or mode == 'sql':
|
|
355 |
if (not mode == 'files') or mode == 'sql': |
|
356 | 356 |
from . import sql |
357 | 357 | |
358 | 358 |
table_name = sql.get_formdef_table_name(self) |
... | ... | |
411 | 411 |
@classmethod |
412 | 412 |
def get_new_id(cls, create=False): |
413 | 413 |
id = super().get_new_id(create=False) |
414 |
if get_publisher().is_using_postgresql(): |
|
415 |
id = cls.get_sql_new_id(id_start=int(id)) |
|
414 |
id = cls.get_sql_new_id(id_start=int(id)) |
|
416 | 415 |
if create: |
417 | 416 |
objects_dir = cls.get_objects_dir() |
418 | 417 |
object_filename = os.path.join(objects_dir, fix_key(id)) |
... | ... | |
443 | 442 |
@classmethod |
444 | 443 |
def wipe(cls): |
445 | 444 |
super().wipe() |
446 |
if get_publisher().is_using_postgresql(): |
|
447 |
cls.sql_wipe() |
|
445 |
cls.sql_wipe() |
|
448 | 446 | |
449 | 447 |
@classmethod |
450 | 448 |
def sql_wipe(cls): |
... | ... | |
457 | 455 |
if self.url_name is None: |
458 | 456 |
# set url name if it's not yet there |
459 | 457 |
self.url_name = self.get_new_url_name() |
458 | ||
459 |
object_only = kwargs.pop('object_only', False) |
|
460 | ||
460 | 461 |
new_internal_identifier = self.get_new_internal_identifier() |
461 | 462 |
if not self.internal_identifier: |
462 | 463 |
self.internal_identifier = new_internal_identifier |
... | ... | |
466 | 467 |
# or if there are not yet any submitted forms (or if site |
467 | 468 |
# is using the SQL storage as internal identifier is not used |
468 | 469 |
# in that mode. |
469 |
if self.id is None or get_publisher().is_using_postgresql() or not (self.data_class().exists()):
|
|
470 |
if self.id is None or not self.data_class().exists():
|
|
470 | 471 |
self.internal_identifier = new_internal_identifier |
471 |
object_only = kwargs.pop('object_only', False) |
|
472 | 472 | |
473 | 473 |
if not object_only: |
474 | 474 |
self.update_relations() |
... | ... | |
487 | 487 |
self.store_related_custom_views() |
488 | 488 | |
489 | 489 |
def update_storage(self): |
490 |
if not get_publisher().is_using_postgresql(): |
|
491 |
return |
|
492 | ||
493 | 490 |
from . import sql |
494 | 491 | |
495 | 492 |
actions = sql.do_formdef_tables(self, rebuild_views=True, rebuild_global_views=True) |
... | ... | |
1919 | 1916 |
status.id in status_mapping for status in old_workflow.possible_status |
1920 | 1917 |
), 'a status was not mapped' |
1921 | 1918 | |
1922 |
unmapped_status_suffix = '-invalid-%s' % str(self.workflow_id or 'default') |
|
1923 | 1919 |
mapping = {} |
1924 | 1920 |
for old_status, new_status in status_mapping.items(): |
1925 | 1921 |
mapping['wf-%s' % old_status] = 'wf-%s' % new_status |
... | ... | |
1927 | 1923 | |
1928 | 1924 |
if any(x[0] != x[1] for x in mapping.items()): |
1929 | 1925 |
# if there are status changes, update all formdatas (except drafts) |
1930 |
if get_publisher().is_using_postgresql(): |
|
1931 |
from . import sql |
|
1932 | ||
1933 |
sql.formdef_remap_statuses(self, mapping) |
|
1934 |
else: |
|
1926 |
from . import sql |
|
1935 | 1927 | |
1936 |
def map_status(status): |
|
1937 |
if status is None: |
|
1938 |
return None |
|
1939 |
elif status in mapping: |
|
1940 |
return mapping[status] |
|
1941 |
elif '-invalid-' in status: |
|
1942 |
return status |
|
1943 |
else: |
|
1944 |
return '%s%s' % (status, unmapped_status_suffix) |
|
1945 | ||
1946 |
for formdata in self.data_class().select([StrictNotEqual('status', 'draft')]): |
|
1947 |
formdata.status = map_status(formdata.status) |
|
1948 |
if formdata.evolution: |
|
1949 |
for evo in formdata.evolution: |
|
1950 |
evo.status = map_status(evo.status) |
|
1951 |
formdata.store() |
|
1928 |
sql.formdef_remap_statuses(self, mapping) |
|
1952 | 1929 | |
1953 | 1930 |
self.workflow = new_workflow |
1954 | 1931 |
if new_workflow.has_action('geolocate') and not self.geolocations: |
wcs/forms/backoffice.py | ||
---|---|---|
46 | 46 |
): |
47 | 47 |
# noqa pylint: disable=too-many-arguments |
48 | 48 | |
49 |
using_postgresql = get_publisher().is_using_postgresql() |
|
50 | ||
51 | 49 |
if not items: |
52 | 50 |
if offset and not limit: |
53 | 51 |
limit = int(get_publisher().get_site_option('default-page-size') or 20) |
54 | 52 |
if not criterias: |
55 | 53 |
criterias = [] |
56 |
if using_postgresql: |
|
57 |
criterias.append(Null('anonymised')) |
|
54 |
criterias.append(Null('anonymised')) |
|
58 | 55 |
items, total_count = self.get_listing_items( |
59 | 56 |
fields, |
60 | 57 |
selected_filter, |
... | ... | |
101 | 98 |
r += htmltext('</colgroup>') |
102 | 99 | |
103 | 100 |
r += htmltext('<thead><tr>') |
104 |
if self.formdef.workflow.criticality_levels and using_postgresql:
|
|
101 |
if self.formdef.workflow.criticality_levels: |
|
105 | 102 |
r += htmltext( |
106 | 103 |
'<th class="criticality-level-cell" data-field-sort-key="criticality_level"><span></span></th>' |
107 | 104 |
) |
... | ... | |
127 | 124 |
else: |
128 | 125 |
field_sort_key = 'f%s' % f.contextual_id |
129 | 126 | |
130 |
if field_sort_key and using_postgresql:
|
|
127 |
if field_sort_key: |
|
131 | 128 |
r += htmltext('<th data-field-sort-key="%s">') % field_sort_key |
132 | 129 |
else: |
133 | 130 |
r += htmltext('<th>') |
... | ... | |
144 | 141 |
r += htmltext('</tbody>') |
145 | 142 |
r += htmltext('</table>') |
146 | 143 | |
147 |
if get_publisher().is_using_postgresql(): |
|
148 |
# add links to paginate |
|
149 |
r += pagination_links(offset, limit, total_count) |
|
144 |
# add links to paginate |
|
145 |
r += pagination_links(offset, limit, total_count) |
|
150 | 146 | |
151 | 147 |
return r.getvalue() |
152 | 148 | |
... | ... | |
159 | 155 |
user=None, |
160 | 156 |
criterias=None, |
161 | 157 |
anonymise=False, |
162 |
): |
|
163 |
if get_publisher().is_using_postgresql(): |
|
164 |
return self.get_listing_item_ids_sql( |
|
165 |
selected_filter, selected_filter_operator, query, order_by, user, criterias, anonymise |
|
166 |
) |
|
167 | ||
168 |
def get_all_except_drafts(): |
|
169 |
item_ids = formdata_class.keys() |
|
170 |
drafts = formdata_class.get_ids_with_indexed_value('status', 'draft') |
|
171 |
return [x for x in item_ids if x not in drafts] |
|
172 | ||
173 |
formdata_class = self.formdef.data_class() |
|
174 |
# used for postgresql mode only |
|
175 |
if selected_filter == 'all': |
|
176 |
if selected_filter_operator == 'ne': |
|
177 |
# nothing |
|
178 |
item_ids = [] |
|
179 |
else: |
|
180 |
# all except drafts |
|
181 |
item_ids = get_all_except_drafts() |
|
182 |
elif selected_filter == 'waiting': |
|
183 |
user_roles = [logged_users_role().id] + user.get_roles() |
|
184 |
waiting_item_ids = formdata_class.get_actionable_ids(user_roles) |
|
185 |
if selected_filter_operator == 'ne': |
|
186 |
# select all ids except drafts |
|
187 |
item_ids = get_all_except_drafts() |
|
188 |
# exclude waiting ids |
|
189 |
item_ids = [x for x in item_ids if x not in waiting_item_ids] |
|
190 |
else: |
|
191 |
# only waiting ids |
|
192 |
item_ids = waiting_item_ids |
|
193 |
else: |
|
194 |
# build selected status list |
|
195 |
applied_filters = [] |
|
196 |
if selected_filter == 'pending': |
|
197 |
applied_filters = ['wf-%s' % x.id for x in self.formdef.workflow.get_not_endpoint_status()] |
|
198 |
elif selected_filter == 'done': |
|
199 |
applied_filters = ['wf-%s' % x.id for x in self.formdef.workflow.get_endpoint_status()] |
|
200 |
else: |
|
201 |
applied_filters = ['wf-%s' % selected_filter] |
|
202 | ||
203 |
filtered_item_ids = [] |
|
204 |
for status_id in applied_filters: |
|
205 |
filtered_item_ids.extend( |
|
206 |
formdata_class.get_ids_with_indexed_value( |
|
207 |
'status', |
|
208 |
status_id, |
|
209 |
) |
|
210 |
) |
|
211 |
if selected_filter_operator == 'ne': |
|
212 |
# select all ids except drafts |
|
213 |
item_ids = get_all_except_drafts() |
|
214 |
# exclude selected status list |
|
215 |
item_ids = [x for x in item_ids if x not in filtered_item_ids] |
|
216 |
else: |
|
217 |
# only selected status list |
|
218 |
item_ids = filtered_item_ids |
|
219 | ||
220 |
if query: |
|
221 |
query_ids = formdata_class.get_ids_from_query(query) |
|
222 |
item_ids = list(set(item_ids).intersection(query_ids)) |
|
223 | ||
224 |
if criterias: |
|
225 |
select_ids = formdata_class.keys(clause=criterias) |
|
226 |
item_ids = list(set(item_ids).intersection(select_ids)) |
|
227 | ||
228 |
if item_ids and not anonymise: |
|
229 |
# as we are in the backoffice, we don't have to care about the |
|
230 |
# situation where the user is the submitter, and we limit ourselves |
|
231 |
# to consider treating roles. |
|
232 |
if not user.is_admin: |
|
233 |
user_roles = set(user.get_roles()) |
|
234 |
concerned_ids = set() |
|
235 |
for role in user_roles: |
|
236 |
concerned_ids |= set( |
|
237 |
formdata_class.get_ids_with_indexed_value('concerned_roles', str(role)) |
|
238 |
) |
|
239 |
item_ids = list(set(item_ids).intersection(concerned_ids)) |
|
240 | ||
241 |
return item_ids |
|
242 | ||
243 |
def get_listing_item_ids_sql( |
|
244 |
self, |
|
245 |
selected_filter, |
|
246 |
selected_filter_operator, |
|
247 |
query, |
|
248 |
order_by, |
|
249 |
user, |
|
250 |
criterias, |
|
251 |
anonymise, |
|
252 | 158 |
): |
253 | 159 |
formdata_class = self.formdef.data_class() |
254 | 160 |
criterias = [] or criterias[:] |
... | ... | |
354 | 260 |
criterias=criterias, |
355 | 261 |
anonymise=anonymise, |
356 | 262 |
) |
357 |
if not get_publisher().is_using_postgresql(): |
|
358 |
item_ids.sort(key=int) |
|
359 |
item_ids.reverse() |
|
360 | 263 | |
361 | 264 |
total_count = len(item_ids) |
362 | 265 | |
... | ... | |
364 | 267 |
offset = 0 |
365 | 268 | |
366 | 269 |
kwargs = {} |
367 |
if get_publisher().is_using_postgresql(): |
|
368 |
kwargs['fields'] = fields |
|
270 |
kwargs['fields'] = fields |
|
369 | 271 | |
370 | 272 |
if limit: |
371 | 273 |
items = formdata_class.get_ids(item_ids[offset : offset + limit], keep_order=True, **kwargs) |
wcs/publisher.py | ||
---|---|---|
132 | 132 | |
133 | 133 |
DeprecationsScanAfterJob().execute() |
134 | 134 | |
135 |
def is_using_postgresql(self): |
|
136 |
return True |
|
137 | ||
138 | 135 |
def has_postgresql_config(self): |
139 | 136 |
return bool(self.cfg.get('postgresql', {})) |
140 | 137 | |
... | ... | |
467 | 464 | |
468 | 465 |
def cleanup(self): |
469 | 466 |
self._cached_user_fields_formdef = None |
470 |
if self.is_using_postgresql(): |
|
471 |
from . import sql |
|
467 |
from . import sql |
|
472 | 468 | |
473 |
sql.cleanup_connection()
|
|
469 |
sql.cleanup_connection() |
|
474 | 470 | |
475 | 471 |
@contextmanager |
476 | 472 |
def complex_data(self): |
wcs/qommon/cron.py | ||
---|---|---|
84 | 84 |
jobs = delayed_jobs |
85 | 85 |
else: |
86 | 86 |
# reindex user and formdata if needed (should only be run once) |
87 |
if publisher.is_using_postgresql(): |
|
88 |
publisher.reindex_sql() |
|
87 |
publisher.reindex_sql() |
|
89 | 88 | |
90 | 89 |
jobs = [] |
91 | 90 |
wcs/qommon/tokens.py | ||
---|---|---|
19 | 19 |
import string |
20 | 20 | |
21 | 21 |
from django.utils.timezone import make_aware, now |
22 |
from quixote import get_publisher |
|
23 | 22 | |
24 | 23 |
from .storage import Equal, Less, StorableObject |
25 | 24 | |
... | ... | |
75 | 74 | |
76 | 75 |
@classmethod |
77 | 76 |
def clean(cls): |
78 |
if get_publisher().is_using_postgresql(): |
|
79 |
# noqa pylint: disable=unexpected-keyword-arg |
|
80 |
cls.wipe(clause=[Less('expiration', now())]) |
|
81 |
else: |
|
82 |
for token_id in cls.keys(): |
|
83 |
try: |
|
84 |
cls.get(token_id) # will run migrate, will check expiration |
|
85 |
except KeyError: |
|
86 |
pass |
|
87 |
except AttributeError: |
|
88 |
# old python2 tokens: |
|
89 |
# AttributeError: module 'builtins' has no attribute 'unicode' |
|
90 |
cls.remove_object(token_id) |
|
77 |
# noqa pylint: disable=unexpected-keyword-arg |
|
78 |
cls.wipe(clause=[Less('expiration', now())]) |
wcs/sql.py | ||
---|---|---|
1581 | 1581 | |
1582 | 1582 |
@guard_postgres |
1583 | 1583 |
def redo_views(conn, cur, formdef, rebuild_global_views=False): |
1584 |
if get_publisher().get_site_option('postgresql_views') == 'false': |
|
1585 |
return |
|
1586 | ||
1587 | 1584 |
if formdef.id is None: |
1588 | 1585 |
return |
1589 | 1586 | |
... | ... | |
1961 | 1958 |
sql_statement += ' WHERE ' + ' AND '.join(where_clauses) |
1962 | 1959 |
sql_statement += ' LIMIT 1' |
1963 | 1960 |
conn, cur = get_connection_and_cursor() |
1964 |
cur.execute(sql_statement, parameters) |
|
1965 |
check = cur.fetchone() |
|
1966 |
result = check is not None |
|
1961 |
try: |
|
1962 |
cur.execute(sql_statement, parameters) |
|
1963 |
except psycopg2.errors.UndefinedTable: |
|
1964 |
result = False |
|
1965 |
else: |
|
1966 |
check = cur.fetchone() |
|
1967 |
result = check is not None |
|
1967 | 1968 |
conn.commit() |
1968 | 1969 |
cur.close() |
1969 | 1970 |
return result |
wcs/statistics/views.py | ||
---|---|---|
19 | 19 |
from django.http import HttpResponseBadRequest, HttpResponseForbidden, JsonResponse |
20 | 20 |
from django.urls import reverse |
21 | 21 |
from django.views.generic import View |
22 |
from quixote import get_publisher |
|
23 | 22 | |
24 | 23 |
from wcs import sql |
25 | 24 |
from wcs.api_utils import is_url_signed |
... | ... | |
42 | 41 | |
43 | 42 |
class IndexView(RestrictedView): |
44 | 43 |
def get(self, request, *args, **kwargs): |
45 |
if not get_publisher().is_using_postgresql(): |
|
46 |
return JsonResponse({'data': [], 'err': 0}) |
|
47 | ||
48 | 44 |
categories = Category.select() |
49 | 45 |
categories.sort(key=lambda x: misc.simplify(x.name)) |
50 | 46 |
category_options = [{'id': '_all', 'label': C_('categories|All')}] + [ |
... | ... | |
306 | 302 |
for status in waitpoint_status: |
307 | 303 |
options.append((status.id, status.name)) |
308 | 304 |
elif field.type in ('item', 'items'): |
309 |
if not get_publisher().is_using_postgresql(): |
|
310 |
continue |
|
311 | 305 |
options = form_page.get_item_filter_options(field, selected_filter='all', anonymised=True) |
312 | 306 |
if not options: |
313 | 307 |
continue |
wcs/users.py | ||
---|---|---|
188 | 188 | |
189 | 189 |
@classmethod |
190 | 190 |
def get_users_with_roles(cls, included_roles=None, excluded_roles=None, order_by=None): |
191 |
if not get_publisher().is_using_postgresql(): |
|
192 |
return [] |
|
193 | ||
194 | 191 |
from wcs import sql |
195 | 192 | |
196 | 193 |
criterias = [sql.Null('deleted_timestamp')] |
wcs/variables.py | ||
---|---|---|
69 | 69 |
) |
70 | 70 | |
71 | 71 |
def order_by(self, attribute): |
72 |
if get_publisher().is_using_postgresql(): |
|
73 |
field = self.get_field(attribute) |
|
74 |
else: |
|
75 |
field = None # no support for field search |
|
72 |
field = self.get_field(attribute) |
|
76 | 73 |
return self._clone(self._criterias, order_by=field or attribute) |
77 | 74 | |
78 | 75 |
def limit(self, limit): |
wcs/wf/jump.py | ||
---|---|---|
340 | 340 |
) if job else contextlib.ExitStack(): |
341 | 341 |
formdata_class = formdef.data_class() |
342 | 342 |
for status_id in status_ids: |
343 |
if publisher.is_using_postgresql(): |
|
344 |
# get minimum delay for jumps in this status |
|
345 |
delay = math.inf |
|
346 |
for jump_action in wfs_status[str(formdef.workflow_id)][status_id]: |
|
347 |
if Template.is_template_string(jump_action.timeout): |
|
348 |
delay = 0 |
|
349 |
break |
|
350 |
delay = min(delay, int(jump_action.timeout)) |
|
351 |
# limit delay to minimal delay |
|
352 |
if delay < JUMP_TIMEOUT_INTERVAL * 60: |
|
353 |
delay = JUMP_TIMEOUT_INTERVAL * 60 |
|
354 | ||
355 |
criterias = [ |
|
356 |
Equal('status', status_id), |
|
357 |
LessOrEqual( |
|
358 |
'last_update_time', |
|
359 |
(datetime.datetime.now() - datetime.timedelta(seconds=delay)).timetuple(), |
|
360 |
), |
|
361 |
] |
|
362 |
formdatas = formdata_class.select_iterator(criterias, ignore_errors=True, itersize=200) |
|
363 |
else: |
|
364 |
formdatas = formdata_class.get_with_indexed_value('status', status_id, ignore_errors=True) |
|
343 |
# get minimum delay for jumps in this status |
|
344 |
delay = math.inf |
|
345 |
for jump_action in wfs_status[str(formdef.workflow_id)][status_id]: |
|
346 |
if Template.is_template_string(jump_action.timeout): |
|
347 |
delay = 0 |
|
348 |
break |
|
349 |
delay = min(delay, int(jump_action.timeout)) |
|
350 |
# limit delay to minimal delay |
|
351 |
if delay < JUMP_TIMEOUT_INTERVAL * 60: |
|
352 |
delay = JUMP_TIMEOUT_INTERVAL * 60 |
|
353 | ||
354 |
criterias = [ |
|
355 |
Equal('status', status_id), |
|
356 |
LessOrEqual( |
|
357 |
'last_update_time', |
|
358 |
(datetime.datetime.now() - datetime.timedelta(seconds=delay)).timetuple(), |
|
359 |
), |
|
360 |
] |
|
361 |
formdatas = formdata_class.select_iterator(criterias, ignore_errors=True, itersize=200) |
|
365 | 362 | |
366 | 363 |
for formdata in formdatas: |
367 | 364 |
for jump_action in wfs_status[str(formdef.workflow_id)][formdata.status]: |
368 |
- |