0001-misc-forbid-some-reserved-values-keywords-to-be-used.patch
tests/admin_pages/test_form.py | ||
---|---|---|
1345 | 1345 |
app.get('/backoffice/forms/1/fields/', status=200) # ok, no error |
1346 | 1346 | |
1347 | 1347 | |
1348 |
def test_form_field_varname_values(pub): |
|
1349 |
create_superuser(pub) |
|
1350 |
create_role(pub) |
|
1351 | ||
1352 |
FormDef.wipe() |
|
1353 |
formdef = FormDef() |
|
1354 |
formdef.name = 'form title' |
|
1355 |
formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] |
|
1356 |
formdef.store() |
|
1357 | ||
1358 |
app = login(get_app(pub)) |
|
1359 |
resp = app.get('/backoffice/forms/1/fields/1/') |
|
1360 | ||
1361 |
resp.forms[0]['varname'] = 'id' |
|
1362 |
resp = resp.forms[0].submit('submit') |
|
1363 |
assert 'this value is reserved for internal use.' in resp.text |
|
1364 | ||
1365 |
resp.forms[0]['varname'] = '0123' |
|
1366 |
resp = resp.forms[0].submit('submit') |
|
1367 |
assert 'must only consist of letters, numbers, or underscore' in resp.text |
|
1368 | ||
1369 |
resp.forms[0]['varname'] = 'plop' |
|
1370 |
resp = resp.forms[0].submit('submit') |
|
1371 |
formdef.refresh_from_storage() |
|
1372 |
assert formdef.fields[0].varname == 'plop' |
|
1373 | ||
1374 | ||
1348 | 1375 |
def test_form_delete_field(pub): |
1349 | 1376 |
create_superuser(pub) |
1350 | 1377 |
create_role(pub) |
wcs/qommon/form.py | ||
---|---|---|
1569 | 1569 |
ValidatedStringWidget._parse(self, request) |
1570 | 1570 |
if self.error: |
1571 | 1571 |
self.error = _('must only consist of letters, numbers, or underscore') |
1572 |
# forbid id/text to be used as identifier, as they would clash against |
|
1573 |
# "native" id/text keys in datasources, and forbid all reserved Python |
|
1574 |
# keywords so varnames can be used in dotted expressions (form.var.plop). |
|
1575 |
# https://docs.python.org/3/reference/lexical_analysis.html#keywords |
|
1576 |
if self.value in ( |
|
1577 |
'id', |
|
1578 |
'text', |
|
1579 |
'and', |
|
1580 |
'as', |
|
1581 |
'assert', |
|
1582 |
'async', |
|
1583 |
'await', |
|
1584 |
'break', |
|
1585 |
'class', |
|
1586 |
'continue', |
|
1587 |
'def', |
|
1588 |
'del', |
|
1589 |
'elif', |
|
1590 |
'else', |
|
1591 |
'except', |
|
1592 |
'False', |
|
1593 |
'finally', |
|
1594 |
'for', |
|
1595 |
'from', |
|
1596 |
'global', |
|
1597 |
'if', |
|
1598 |
'import', |
|
1599 |
'in', |
|
1600 |
'is', |
|
1601 |
'lambda', |
|
1602 |
'None', |
|
1603 |
'nonlocal', |
|
1604 |
'not', |
|
1605 |
'or', |
|
1606 |
'pass', |
|
1607 |
'raise', |
|
1608 |
'return', |
|
1609 |
'True', |
|
1610 |
'try', |
|
1611 |
'while', |
|
1612 |
'with', |
|
1613 |
'yield', |
|
1614 |
): |
|
1615 |
self.error = _('this value is reserved for internal use.') |
|
1572 | 1616 | |
1573 | 1617 | |
1574 | 1618 |
class SlugWidget(ValidatedStringWidget): |
1575 |
- |