Skip to content

Commit 51e2de4

Browse files
add: check the "name" setting as well as "form_name"
- it's possible to set the primary instance root node name via the setting "name" (which overrides other ways to set the name), so check the settings code path as well.
1 parent 3e497c9 commit 51e2de4

4 files changed

Lines changed: 62 additions & 8 deletions

File tree

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1+
from pyxform import constants as co
12
from pyxform.errors import ErrorCode, PyXFormError
23
from pyxform.parsing.expression import is_xml_tag
34

45

5-
def validate_form_name(form_name: str | None):
6+
def validate_name(name: str | None, from_sheet: bool = True):
67
"""
7-
The form_name must be a valid XML tag since it is used for the primary instance element.
8+
The name must be a valid XML Name since it is used for the primary instance element.
89
9-
:param form_name: The value to check.
10+
:param name: The value to check.
11+
:param from_sheet: If True, the value is from the settings sheet (rather than the
12+
file name or form_name API usage), so the sheet name should be included in the
13+
error (if any).
1014
"""
11-
if form_name is not None and not is_xml_tag(value=form_name):
12-
raise PyXFormError(ErrorCode.NAMES_009.value.format(name="form_name"))
15+
if name is not None and not is_xml_tag(value=name):
16+
if from_sheet:
17+
raise PyXFormError(
18+
ErrorCode.NAMES_008.value.format(sheet=co.SETTINGS, row=1, column=co.NAME)
19+
)
20+
else:
21+
raise PyXFormError(ErrorCode.NAMES_009.value.format(name="form_name"))

pyxform/xls2json.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def workbook_to_json(
264264
raise PyXFormError(msg)
265265

266266
# Make sure the passed in vars are unicode
267-
validate_settings.validate_form_name(form_name=form_name)
267+
validate_settings.validate_name(name=form_name, from_sheet=False)
268268
form_name = str(coalesce(form_name, constants.DEFAULT_FORM_NAME))
269269
default_language = str(coalesce(default_language, constants.DEFAULT_LANGUAGE_VALUE))
270270

@@ -308,6 +308,7 @@ def workbook_to_json(
308308
header_columns=set(Survey.get_slot_names()),
309309
)
310310
settings = settings_sheet.data[0]
311+
validate_settings.validate_name(name=settings.get(constants.NAME, None))
311312
else:
312313
similar = find_sheet_misspellings(key=constants.SETTINGS, keys=sheet_names)
313314
if similar is not None:

tests/test_settings.py

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from pyxform import constants as co
12
from pyxform.errors import ErrorCode
23

34
from tests.pyxform_test_case import PyxformTestCase
@@ -43,7 +44,39 @@ def test_form_id(self):
4344
xml__xpath_match=[xps.form_id("my_form")],
4445
)
4546

46-
def test_form_name__valid_characters(self):
47+
def test_name__from_sheet__valid_characters(self):
48+
"""Should allow a custom name with valid characters."""
49+
md = """
50+
| settings |
51+
| | name |
52+
| | master-form_v2.1 |
53+
54+
| survey |
55+
| | type | name | label |
56+
| | text | q1 | hello |
57+
"""
58+
self.assertPyxformXform(md=md, xml__xpath_match=[xps.name("master-form_v2.1")])
59+
60+
def test_name__from_sheet__invalid_characters__error(self):
61+
"""Should raise an error if the form_name is not a valid name."""
62+
md = """
63+
| settings |
64+
| | name |
65+
| | bad@filename |
66+
67+
| survey |
68+
| | type | name | label |
69+
| | text | q1 | hello |
70+
"""
71+
self.assertPyxformXform(
72+
md=md,
73+
errored=True,
74+
error__contains=[
75+
ErrorCode.NAMES_008.value.format(sheet=co.SETTINGS, row=1, column=co.NAME)
76+
],
77+
)
78+
79+
def test_name__from_file__valid_characters(self):
4780
"""Should allow a custom form_name with valid characters."""
4881
md = """
4982
| survey |
@@ -53,9 +86,10 @@ def test_form_name__valid_characters(self):
5386
self.assertPyxformXform(
5487
md=md,
5588
name="master-form_v2.1",
89+
xml__xpath_match=[xps.name("master-form_v2.1")],
5690
)
5791

58-
def test_form_name__invalid_characters__error(self):
92+
def test_name__from_file__invalid_characters__error(self):
5993
"""Should raise an error if the form_name is not a valid name."""
6094
md = """
6195
| survey |

tests/xpath_helpers/settings.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ def form_id(value: str) -> str:
1717
/h:html/h:head/x:model/x:instance/x:test_name/@id[.='{value}']
1818
"""
1919

20+
@staticmethod
21+
def name(value: str) -> str:
22+
"""The primary instance root node name is set to this value."""
23+
return f"""
24+
/h:html/h:head/x:model/x:instance/*[
25+
namespace-uri()='http://www.w3.org/2002/xforms'
26+
and local-name()='{value}'
27+
]
28+
"""
29+
2030
@staticmethod
2131
def language_is_default(lang: str) -> str:
2232
"""The language translation has itext and is marked as the default."""

0 commit comments

Comments
 (0)